OSSP CVS Repository

ossp - Check-in [1018]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1018
Date: 2001-Sep-15 18:03:37 (local)
2001-Sep-15 16:03:37 (UTC)
User:rse
Branch:
Comment: Reduce to the new generated version of PCRE 3.5. This version is just half the size, because all comments and unneccessary whitespaces were stripped.
Tickets:
Inspections:
Files:
ossp-pkg/l2/.cvsignore      1.9 -> 1.10     2 inserted, 2 deleted
ossp-pkg/l2/Makefile.in      1.23 -> 1.24     6 inserted, 7 deleted
ossp-pkg/l2/l2_ut_pcre.c      1.1 -> 1.2     3861 inserted, 5435 deleted
ossp-pkg/l2/l2_ut_pcre.h      1.1 -> 1.2     17 inserted, 29 deleted

ossp-pkg/l2/.cvsignore 1.9 -> 1.10

--- .cvsignore   2001/09/10 11:20:58     1.9
+++ .cvsignore   2001/09/15 16:03:37     1.10
@@ -17,6 +17,6 @@
 shtool
 l2-config.1
 l2.3
-l2_ut_pcre_gen
-l2_ut_pcre_tab.c
+l2_ut_pcre.gen
+l2_ut_pcre.tab
 l2.h


ossp-pkg/l2/Makefile.in 1.23 -> 1.24

--- Makefile.in  2001/09/13 14:44:40     1.23
+++ Makefile.in  2001/09/15 16:03:37     1.24
@@ -149,12 +149,11 @@
             -version-info `$(SHTOOL) version -l c -d libtool l2_version.c`
 
 #   build regex library
-l2_ut_pcre.lo: l2_ut_pcre.c
-l2_ut_pcre.c: l2_ut_pcre_tab.c
-l2_ut_pcre_tab.c: l2_ut_pcre_gen
-        ./l2_ut_pcre_gen >l2_ut_pcre_tab.c
-l2_ut_pcre_gen:
-        $(CC) $(CFLAGS) -DL2_UT_PCRE_GENTAB $(LDFLAGS) -o l2_ut_pcre_gen l2_ut_pcre.c $(LIBS)
+l2_ut_pcre.lo: l2_ut_pcre.tab l2_ut_pcre.c
+l2_ut_pcre.tab: l2_ut_pcre.c
+        $(CC) $(CFLAGS) -DL2_UT_PCRE_TAB $(LDFLAGS) -o l2_ut_pcre.gen l2_ut_pcre.c $(LIBS)
+        ./l2_ut_pcre.gen >l2_ut_pcre.tab
+        -$(RM) l2_ut_pcre.gen
 
 #   build test suite programs
 l2_test: l2_test.o libl2.la
@@ -247,7 +246,7 @@
         $(RM) libtool
         $(RM) Makefile
         $(RM) l2_test.log
-        $(RM) l2_ut_pcre_gen l2_ut_pcre_tab.c
+        $(RM) l2_ut_pcre.tab
         $(RM) l2.h
 
 #   remove everything which can be regenerated


ossp-pkg/l2/l2_ut_pcre.c 1.1 -> 1.2

--- l2_ut_pcre.c 2001/09/04 14:52:28     1.1
+++ l2_ut_pcre.c 2001/09/15 16:03:37     1.2
@@ -1,50 +1,50 @@
-/*************************************************
-*      Perl-Compatible Regular Expressions       *
-*************************************************/
+/* 
+ *  Perl Compatible Regular Expression (PCRE) Library
+ *  Copyright (c) 1997-2001 Philip Hazel <ph10@cam.ac.uk>
+ *  Copyright (c) 1997-2001 University of Cambridge
+ *
+ *  DO NOT EDIT THIS FILE, IT WAS AUTOMATICALLY GENERATED!
+ *
+ *  This is an automatically generated, extremely stripped down
+ *  version of the PCRE 3.5 library from the Philip Hazel.
+ *  This version is still distributed under the same original PCRE
+ *  Open Source license, but Philip Hazel is no longer responsible
+ *  for this version.
+ */
+
+/* 
+   This 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. See
+   the file Tech.Notes for some information on the internals.
+
+   Written by: Philip Hazel <ph10@cam.ac.uk>
+
+   Copyright (c) 1997-2001 University of Cambridge
+
+   -----------------------------------------------------------------------------
+   Permission is granted to anyone to use this software for any purpose on any
+   computer system, and to redistribute it freely, subject to the following
+   restrictions:
+
+   1. This software 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.
 
-/*
-This 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. See
-the file Tech.Notes for some information on the internals.
+   2. The origin of this software must not be misrepresented, either by explicit
+   claim or by omission.
 
-Written by: Philip Hazel <ph10@cam.ac.uk>
-
-           Copyright (c) 1997-2001 University of Cambridge
-
------------------------------------------------------------------------------
-Permission is granted to anyone to use this software for any purpose on any
-computer system, and to redistribute it freely, subject to the following
-restrictions:
-
-1. This software 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.
-
-2. The origin of this software must not be misrepresented, either by
-   explicit claim or by omission.
-
-3. Altered versions must be plainly marked as such, and must not be
+   3. Altered versions must be plainly marked as such, and must not be
    misrepresented as being the original software.
 
-4. If PCRE is embedded in any software that is released under the GNU
-   General Purpose Licence (GPL), then the terms of that licence shall
-   supersede any condition above with which it is incompatible.
------------------------------------------------------------------------------
-*/
-
-/* ____ BEGIN internal.h ____ */
-
-/* This header contains definitions that are shared between the different
-modules, but which are not relevant to the outside. */
-
-/* Get the definitions provided by running "configure" */
+   4. If PCRE is embedded in any software that is released under the GNU General
+   Purpose Licence (GPL), then the terms of that licence shall supersede any
+   condition above with which it is incompatible.
+   ----------------------------------------------------------------------------- */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-/* Standard C headers plus the external interface definition */
-
 #include <ctype.h>
 #include <limits.h>
 #include <stddef.h>
@@ -53,35 +53,19 @@
 #include <string.h>
 #include "l2_ut_pcre.h"
 
-/* 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 options flags start at the most significant end of the four bytes,
-but skip the top bit so we can use ints for convenience without getting tangled
-with negative values. The public options defined in pcre.h start at the least
-significant end. Make sure they don't overlap, though now that we have expanded
-to four bytes there is plenty of space. */
-
-#define PCRE_FIRSTSET      0x40000000  /* first_char is set */
-#define PCRE_REQCHSET      0x20000000  /* req_char is set */
-#define PCRE_STARTLINE     0x10000000  /* start after \n for multiline */
-#define PCRE_INGROUP       0x08000000  /* compiling inside a group */
-#define PCRE_ICHANGED      0x04000000  /* i option changes within regex */
-
-/* Options for the "extra" block produced by pcre_study(). */
+#define PCRE_FIRSTSET      0x40000000
+#define PCRE_REQCHSET      0x20000000
+#define PCRE_STARTLINE     0x10000000
+#define PCRE_INGROUP       0x08000000
+#define PCRE_ICHANGED      0x04000000
 
-#define PCRE_STUDY_MAPPED   0x01     /* a map of starting chars exists */
-
-/* Masks for identifying the public options which are permitted at compile
-time, run time or study time, respectively. */
+#define PCRE_STUDY_MAPPED   0x01
 
 #define PUBLIC_OPTIONS \
   (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
@@ -90,13 +74,9 @@
 #define PUBLIC_EXEC_OPTIONS \
   (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
 
-#define PUBLIC_STUDY_OPTIONS 0   /* None defined */
-
-/* Magic number to provide a small check against being handed junk. */
+#define PUBLIC_STUDY_OPTIONS 0
 
-#define MAGIC_NUMBER  0x50435245UL   /* 'PCRE' */
-
-/* Miscellaneous definitions */
+#define MAGIC_NUMBER  0x50435245UL
 
 typedef int BOOL;
 
@@ -107,10 +87,6 @@
 #define TRUE    1
 #endif
 
-/* Escape items that are just an encoding of a particular data value. Note that
-ESC_N is defined as yet another macro, which is set in config.h to either \n
-(the default) or \r (which some people want). */
-
 #ifndef ESC_E
 #define ESC_E 27
 #endif
@@ -131,132 +107,99 @@
 #define ESC_T '\t'
 #endif
 
-/* 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. The final one must be ESC_REF as subsequent
-values are used for \1, \2, \3, etc. There is a test in the code for an escape
-greater than ESC_b and less than ESC_Z to detect the types that may be
-repeated. 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_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w,
-       ESC_Z, ESC_z, ESC_REF };
-
-/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
-that extract substrings. 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. */
+        ESC_Z, ESC_z, ESC_REF
+};
 
 enum {
-  OP_END,
+        OP_END,
 
-  /* Values corresponding to backslashed metacharacters */
+        OP_SOD,
+        OP_NOT_WORD_BOUNDARY,
+        OP_WORD_BOUNDARY,
+        OP_NOT_DIGIT,
+        OP_DIGIT,
+        OP_NOT_WHITESPACE,
+        OP_WHITESPACE,
+        OP_NOT_WORDCHAR,
+        OP_WORDCHAR,
+        OP_EODN,
+        OP_EOD,
+
+        OP_OPT,
+        OP_CIRC,
+        OP_DOLL,
+        OP_ANY,
+        OP_CHARS,
+        OP_NOT,
+
+        OP_STAR,
+        OP_MINSTAR,
+        OP_PLUS,
+        OP_MINPLUS,
+        OP_QUERY,
+        OP_MINQUERY,
+        OP_UPTO,
+        OP_MINUPTO,
+        OP_EXACT,
+
+        OP_NOTSTAR,
+        OP_NOTMINSTAR,
+        OP_NOTPLUS,
+        OP_NOTMINPLUS,
+        OP_NOTQUERY,
+        OP_NOTMINQUERY,
+        OP_NOTUPTO,
+        OP_NOTMINUPTO,
+        OP_NOTEXACT,
+
+        OP_TYPESTAR,
+        OP_TYPEMINSTAR,
+        OP_TYPEPLUS,
+        OP_TYPEMINPLUS,
+        OP_TYPEQUERY,
+        OP_TYPEMINQUERY,
+        OP_TYPEUPTO,
+        OP_TYPEMINUPTO,
+        OP_TYPEEXACT,
+
+        OP_CRSTAR,
+        OP_CRMINSTAR,
+        OP_CRPLUS,
+        OP_CRMINPLUS,
+        OP_CRQUERY,
+        OP_CRMINQUERY,
+        OP_CRRANGE,
+        OP_CRMINRANGE,
+
+        OP_CLASS,
+        OP_REF,
+        OP_RECURSE,
+
+        OP_ALT,
+        OP_KET,
+        OP_KETRMAX,
+        OP_KETRMIN,
+
+        OP_ASSERT,
+        OP_ASSERT_NOT,
+        OP_ASSERTBACK,
+        OP_ASSERTBACK_NOT,
+        OP_REVERSE,
+
+        OP_ONCE,
+        OP_COND,
+        OP_CREF,
 
-  OP_SOD,            /* Start of data: \A */
-  OP_NOT_WORD_BOUNDARY,  /* \B */
-  OP_WORD_BOUNDARY,      /* \b */
-  OP_NOT_DIGIT,          /* \D */
-  OP_DIGIT,              /* \d */
-  OP_NOT_WHITESPACE,     /* \S */
-  OP_WHITESPACE,         /* \s */
-  OP_NOT_WORDCHAR,       /* \W */
-  OP_WORDCHAR,           /* \w */
-  OP_EODN,
-  OP_EOD,
-
-  OP_OPT,            /* Set runtime options */
-  OP_CIRC,           /* Start of line - varies with multiline switch */
-  OP_DOLL,
-  OP_ANY,            /* Match any character */
-  OP_CHARS,          /* Match string of characters */
-  OP_NOT,            /* Match anything but the following char */
-
-  OP_STAR,           /* The maximizing and minimizing versions of */
-  OP_MINSTAR,        /* all these opcodes must come in pairs, with */
-  OP_PLUS,           /* the minimizing one second. */
-  OP_MINPLUS,        /* This first set applies to single characters */
-  OP_QUERY,
-  OP_MINQUERY,
-  OP_UPTO,           /* From 0 to n matches */
-  OP_MINUPTO,
-  OP_EXACT,          /* Exactly n matches */
-
-  OP_NOTSTAR,        /* The maximizing and minimizing versions of */
-  OP_NOTMINSTAR,     /* all these opcodes must come in pairs, with */
-  OP_NOTPLUS,        /* the minimizing one second. */
-  OP_NOTMINPLUS,     /* This first set applies to "not" single characters */
-  OP_NOTQUERY,
-  OP_NOTMINQUERY,
-  OP_NOTUPTO,        /* From 0 to n matches */
-  OP_NOTMINUPTO,
-  OP_NOTEXACT,       /* Exactly n matches */
-
-  OP_TYPESTAR,       /* The maximizing and minimizing versions of */
-  OP_TYPEMINSTAR,    /* all these opcodes must come in pairs, with */
-  OP_TYPEPLUS,       /* the minimizing one second. These codes must */
-  OP_TYPEMINPLUS,    /* be in exactly the same order as those above. */
-  OP_TYPEQUERY,      /* This set applies to character types such as \d */
-  OP_TYPEMINQUERY,
-  OP_TYPEUPTO,       /* From 0 to n matches */
-  OP_TYPEMINUPTO,
-  OP_TYPEEXACT,      /* Exactly n matches */
-
-  OP_CRSTAR,         /* The maximizing and minimizing versions of */
-  OP_CRMINSTAR,      /* all these opcodes must come in pairs, with */
-  OP_CRPLUS,         /* the minimizing one second. These codes must */
-  OP_CRMINPLUS,      /* be in exactly the same order as those above. */
-  OP_CRQUERY,        /* These are for character classes and back refs */
-  OP_CRMINQUERY,
-  OP_CRRANGE,        /* These are different to the three seta above. */
-  OP_CRMINRANGE,
-
-  OP_CLASS,          /* Match a character class */
-  OP_REF,            /* Match a back reference */
-  OP_RECURSE,        /* Match this pattern recursively */
-
-  OP_ALT,            /* Start of alternation */
-  OP_KET,
-  OP_KETRMAX,        /* These two must remain together and in this */
-  OP_KETRMIN,        /* order. They are for groups the repeat for ever. */
-
-  /* The assertions must come before ONCE and COND */
-
-  OP_ASSERT,         /* Positive lookahead */
-  OP_ASSERT_NOT,     /* Negative lookahead */
-  OP_ASSERTBACK,     /* Positive lookbehind */
-  OP_ASSERTBACK_NOT, /* Negative lookbehind */
-  OP_REVERSE,        /* Move pointer back - used in lookbehind assertions */
-
-  /* ONCE 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,           /* Once matched, don't back up into the subpattern */
-  OP_COND,           /* Conditional group */
-  OP_CREF,           /* Used to hold an extraction string number (cond ref) */
-
-  OP_BRAZERO,        /* These two must remain together and in this */
-  OP_BRAMINZERO,     /* order. */
-
-  OP_BRANUMBER,      /* Used for extracting brackets whose number is greater
-                        than can fit into an opcode. */
-
-  OP_BRA             /* This and greater values are used for brackets that
-                        extract substrings up to a basic limit. After that,
-                        use is made of OP_BRANUMBER. */
-};
+        OP_BRAZERO,
+        OP_BRAMINZERO,
 
-/* The highest extraction number before we have to start using additional
-bytes. (Originally PCRE didn't have support for extraction counts highter than
-this number.) The value is limited by the number of opcodes left after OP_BRA,
-i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
-opcodes. */
+        OP_BRANUMBER,
 
-#define EXTRACT_BASIC_MAX  150
+        OP_BRA
+};
 
-/* The texts of compile-time error messages are defined as macros here so that
-they can be accessed by the POSIX wrapper and converted into error codes.  Yes,
-I could have used error codes in the first place, but didn't feel like changing
-just to accommodate the POSIX wrapper. */
+#define EXTRACT_BASIC_MAX  150
 
 #define ERR1  "\\ at end of pattern"
 #define ERR2  "\\c at end of pattern"
@@ -294,97 +237,71 @@
 #define ERR34 "character value in \\x{...} sequence is too large"
 #define ERR35 "invalid condition (?(0)"
 
-/* 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;
 
-/* The real format of the start of the pcre block; the actual code vector
-runs on as long as necessary after the end. */
-
 typedef struct real_pcre {
-  unsigned long int magic_number;
-  size_t size;
-  const unsigned char *tables;
-  unsigned long int options;
-  unsigned short int top_bracket;
-  unsigned short int top_backref;
-  uschar first_char;
-  uschar req_char;
-  uschar code[1];
+        unsigned long int magic_number;
+        size_t size;
+        const unsigned char *tables;
+        unsigned long int options;
+        unsigned short int top_bracket;
+        unsigned short int top_backref;
+        uschar first_char;
+        uschar req_char;
+        uschar code[1];
 } real_pcre;
 
-/* The real format of the extra block returned by pcre_study(). */
-
 typedef struct real_pcre_extra {
-  uschar options;
-  uschar start_bits[32];
+        uschar options;
+        uschar start_bits[32];
 } real_pcre_extra;
 
-/* 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 *lcc;
+        const uschar *fcc;
+        const uschar *cbits;
+        const uschar *ctypes;
 } compile_data;
 
-/* Structure for passing "static" information around between the functions
-doing the matching, so that they are thread-safe. */
-
 typedef struct match_data {
-  int    errorcode;             /* As it says */
-  int   *offset_vector;         /* Offset vector */
-  int    offset_end;            /* One past the end */
-  int    offset_max;            /* The maximum usable for return data */
-  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   endonly;               /* Dollar not before final \n */
-  BOOL   notempty;              /* Empty string match not wanted */
-  const uschar *start_pattern;  /* For use when recursing */
-  const uschar *start_subject;  /* Start of the subject string */
-  const uschar *end_subject;
-  const uschar *start_match;    /* Start of this match attempt */
-  const uschar *end_match_ptr;  /* Subject position at end match */
-  int    end_offset_top;        /* Highwater mark at end of match */
+        int errorcode;
+        int *offset_vector;
+        int offset_end;
+        int offset_max;
+        const uschar *lcc;
+        const uschar *ctypes;
+        BOOL offset_overflow;
+        BOOL notbol;
+        BOOL noteol;
+        BOOL utf8;
+        BOOL endonly;
+        BOOL notempty;
+        const uschar *start_pattern;
+        const uschar *start_subject;
+        const uschar *end_subject;
+        const uschar *start_match;
+        const uschar *end_match_ptr;
+        int end_offset_top;
 } 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   /* alphameric 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 */
+#define ctype_word    0x10
+#define ctype_meta    0x80
 
-/* Offsets of the various tables from the base tables pointer, and
-total length. */
+#define cbit_space     0
+#define cbit_xdigit   32
+#define cbit_digit    64
+#define cbit_upper    96
+#define cbit_lower   128
+#define cbit_word    160
+#define cbit_graph   192
+#define cbit_print   224
+#define cbit_punct   256
+#define cbit_cntrl   288
+#define cbit_length  320
 
 #define lcc_offset      0
 #define fcc_offset    256
@@ -392,155 +309,91 @@
 #define ctypes_offset (cbits_offset + cbit_length)
 #define tables_length (ctypes_offset + 256)
 
-/* ____ END internal.h ____ */
-
-#ifndef L2_UT_PCRE_GENTAB
-
-/* ____ BEGIN pcre.c ____ */
-
-/* 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. I suppose it's only been 10 years... */
-
-/* Include the internals header, which itself includes Standard C headers plus
-the external pcre header. */
-
-/* Allow compilation as C++ source code, should anybody want to do that. */
+#ifndef L2_UT_PCRE_TAB
 
 #ifdef __cplusplus
 #define class pcre_class
 #endif
 
-/* Maximum number of items on the nested bracket stacks at compile time. This
-applies to the nesting of all kinds of parentheses. It does not limit
-un-nested, non-capturing parentheses. This number can be made bigger if
-necessary - it is used to dimension one int and one unsigned char vector at
-compile time. */
-
 #define BRASTACK_SIZE 200
 
-/* The number of bytes in a literal character string above which we can't add
-any more is different when UTF-8 characters may be encountered. */
-
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
 #define MAXLIT 250
 #else
 #define MAXLIT 255
 #endif
 
-/* 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 };
 
-/* Text forms of OP_ values and things, for debugging (not all used) */
-
-/* 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. */
-
 static const short int escapes[] = {
-    0,      0,      0,      0,      0,      0,      0,      0,   /* 0 - 7 */
-    0,      0,    ':',    ';',    '<',    '=',    '>',    '?',   /* 8 - ? */
-  '@', -ESC_A, -ESC_B,      0, -ESC_D,      0,      0,      0,   /* @ - G */
-    0,      0,      0,      0,      0,      0,      0,      0,   /* H - O */
-    0,      0,      0, -ESC_S,      0,      0,      0, -ESC_W,   /* P - W */
-    0,      0, -ESC_Z,    '[',   '\\',    ']',    '^',    '_',   /* X - _ */
-  '`',      7, -ESC_b,      0, -ESC_d,  ESC_E,  ESC_F,      0,   /* ` - g */
-    0,      0,      0,      0,      0,      0,  ESC_N,      0,   /* h - o */
-    0,      0,  ESC_R, -ESC_s,  ESC_T,      0,      0, -ESC_w,   /* p - w */
-    0,      0, -ESC_z                                            /* x - z */
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, ':', ';', '<', '=', '>', '?',
+        '@', -ESC_A, -ESC_B, 0, -ESC_D, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, -ESC_S, 0, 0, 0, -ESC_W,
+        0, 0, -ESC_Z, '[', '\\', ']', '^', '_',
+        '`', 7, -ESC_b, 0, -ESC_d, ESC_E, ESC_F, 0,
+        0, 0, 0, 0, 0, 0, ESC_N, 0,
+        0, 0, ESC_R, -ESC_s, ESC_T, 0, 0, -ESC_w,
+        0, 0, -ESC_z
 };
 
-/* Tables of names of POSIX character classes and their lengths. The list is
-terminated by a zero length entry. The first three must be alpha, upper, lower,
-as this is assumed for handling case independence. */
-
 static const char *posix_names[] = {
-  "alpha", "lower", "upper",
-  "alnum", "ascii", "cntrl", "digit", "graph",
-  "print", "punct", "space", "word",  "xdigit" };
+        "alpha", "lower", "upper",
+        "alnum", "ascii", "cntrl", "digit", "graph",
+        "print", "punct", "space", "word", "xdigit"
+};
 
 static const uschar posix_name_lengths[] = {
-  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
-
-/* Table of class bit maps for each POSIX class; up to three may be combined
-to form the class. */
+        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0
+};
 
 static const int posix_class_maps[] = {
-  cbit_lower, cbit_upper, -1,             /* alpha */
-  cbit_lower, -1,         -1,             /* lower */
-  cbit_upper, -1,         -1,             /* upper */
-  cbit_digit, cbit_lower, cbit_upper,     /* alnum */
-  cbit_print, cbit_cntrl, -1,             /* ascii */
-  cbit_cntrl, -1,         -1,             /* cntrl */
-  cbit_digit, -1,         -1,             /* digit */
-  cbit_graph, -1,         -1,             /* graph */
-  cbit_print, -1,         -1,             /* print */
-  cbit_punct, -1,         -1,             /* punct */
-  cbit_space, -1,         -1,             /* space */
-  cbit_word,  -1,         -1,             /* word */
-  cbit_xdigit,-1,         -1              /* xdigit */
+        cbit_lower, cbit_upper, -1,
+        cbit_lower, -1, -1,
+        cbit_upper, -1, -1,
+        cbit_digit, cbit_lower, cbit_upper,
+        cbit_print, cbit_cntrl, -1,
+        cbit_cntrl, -1, -1,
+        cbit_digit, -1, -1,
+        cbit_graph, -1, -1,
+        cbit_print, -1, -1,
+        cbit_punct, -1, -1,
+        cbit_space, -1, -1,
+        cbit_word, -1, -1,
+        cbit_xdigit, -1, -1
 };
 
-/* Definition to allow mutual recursion */
-
 static BOOL
-  compile_regex(int, int, int *, uschar **, const uschar **, const char **,
-    BOOL, int, int *, int *, compile_data *);
-
-/* Structure for building a chain of data that actually lives on the
-stack, 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. */
+compile_regex(int, int, int *, uschar **, const uschar **, const char **,
+                          BOOL, int, int *, int *, compile_data *);
 
 typedef struct eptrblock {
-  struct eptrblock *prev;
-  const uschar *saved_eptr;
+        struct eptrblock *prev;
+        const uschar *saved_eptr;
 } eptrblock;
 
-/* Flag bits for the match() function */
+#define match_condassert   0x01
+#define match_isgroup      0x02
 
-#define match_condassert   0x01    /* Called to check a condition assertion */
-#define match_isgroup      0x02    /* Set if start of bracketed group */
-
-/*************************************************
-*               Global variables                 *
-*************************************************/
-
-/* PCRE is thread-clean and doesn't use any global variables in the normal
-sense. However, it calls memory allocation and free functions via the two
-indirections below, which are can be changed by the caller, but are shared
-between all threads. */
-
-void *(*pcre_malloc)(size_t) = malloc;
-void  (*pcre_free)(void *) = free;
-
-/*************************************************
-*    Macros and tables for character handling    *
-*************************************************/
-
-/* 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. */
+void *(*pcre_malloc) (size_t) = malloc;
+void (*pcre_free) (void *) = free;
 
 #ifndef L2_UT_PCRE_SUPPORT_UTF8
 #define GETCHARINC(c, eptr) c = *eptr++;
 #define GETCHARLEN(c, eptr, len) c = *eptr;
 #define BACKCHAR(eptr)
 
-#else   /* L2_UT_PCRE_SUPPORT_UTF8 */
-
-/* Get the next UTF-8 character, advancing the pointer */
+#else
 
 #define GETCHARINC(c, eptr) \
   c = *eptr++; \
   if (md->utf8 && (c & 0xc0) == 0xc0) \
     { \
-    int a = utf8_table4[c & 0x3f];  /* Number of additional bytes */ \
-    int s = 6 - a;                  /* Amount to shift next byte */  \
-    c &= utf8_table3[a];            /* Low order bits from first byte */ \
+    int a = utf8_table4[c & 0x3f];   \
+    int s = 6 - a;                    \
+    c &= utf8_table3[a];             \
     while (a-- > 0) \
       { \
       c |= (*eptr++ & 0x3f) << s; \
@@ -548,17 +401,15 @@
       } \
     }
 
-/* Get the next UTF-8 character, not advancing the pointer, setting length */
-
 #define GETCHARLEN(c, eptr, len) \
   c = *eptr; \
   len = 1; \
   if (md->utf8 && (c & 0xc0) == 0xc0) \
     { \
     int i; \
-    int a = utf8_table4[c & 0x3f];  /* Number of additional bytes */ \
-    int s = 6 - a;                  /* Amount to shift next byte */  \
-    c &= utf8_table3[a];            /* Low order bits from first byte */ \
+    int a = utf8_table4[c & 0x3f];   \
+    int s = 6 - a;                    \
+    c &= utf8_table3[a];             \
     for (i = 1; i <= a; i++) \
       { \
       c |= (eptr[i] & 0x3f) << s; \
@@ -567,5189 +418,3780 @@
     len += a; \
     }
 
-/* If the pointer is not at the start of a character, move it back until
-it is. */
-
 #define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--;
 
 #endif
 
-/*************************************************
-*             Default character tables           *
-*************************************************/
-
-/* A default set of character tables is included in the PCRE binary. Its source
-is built by the maketables auxiliary program, which uses the default C ctypes
-functions, and put in the file chartables.c. These tables are used by PCRE
-whenever the caller of pcre_compile() does not provide an alternate set of
-tables. */
-
-#include "l2_ut_pcre_tab.c"
+#include "l2_ut_pcre.tab"
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-/*************************************************
-*           Tables for UTF-8 support             *
-*************************************************/
-
-/* These are the breakpoints for different numbers of bytes in a UTF-8
-character. */
-
-static int utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
 
-/* 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. */
+static int utf8_table1[] =
+        { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff };
 
-static int utf8_table2[] = { 0,    0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
-static int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
-
-/* Table of the number of extra characters, indexed by the first character
-masked with 0x3f. The highest number for a valid UTF-8 character is in fact
-0x3d. */
+static int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
+static int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
 
 static uschar 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 };
-
-/*************************************************
-*       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
-*/
+        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
+};
 
-static int
-ord2utf8(int cvalue, uschar *buffer)
+static int ord2utf8(int cvalue, uschar * buffer)
 {
-register int i, j;
-for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
-  if (cvalue <= utf8_table1[i]) break;
-*buffer++ = utf8_table2[i] | (cvalue & utf8_table3[i]);
-cvalue >>= 6 - i;
-for (j = 0; j < i; j++)
-  {
-  *buffer++ = 0x80 | (cvalue & 0x3f);
-  cvalue >>= 6;
-  }
-return i + 1;
+        register int i, j;
+        for (i = 0; i < sizeof (utf8_table1) / sizeof (int); i++)
+                if (cvalue <= utf8_table1[i])
+                        break;
+        *buffer++ = utf8_table2[i] | (cvalue & utf8_table3[i]);
+        cvalue >>= 6 - i;
+        for (j = 0; j < i; j++) {
+                *buffer++ = 0x80 | (cvalue & 0x3f);
+                cvalue >>= 6;
+        }
+        return i + 1;
 }
 #endif
 
-/*************************************************
-*          Return version string                 *
-*************************************************/
-
 #define STRING(a)  # a
 #define XSTRING(s) STRING(s)
 
-const char *
-pcre_version(void)
+const char *pcre_version(void)
 {
-return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE);
+        return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE);
 }
 
-/*************************************************
-* (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:
-  external_re   points to compiled code
-  optptr        where to pass back the options
-  first_char    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
-*/
-
-int
-pcre_info(const pcre *external_re, int *optptr, int *first_char)
+int pcre_info(const pcre * external_re, int *optptr, int *first_char)
 {
-const real_pcre *re = (const real_pcre *)external_re;
-if (re == NULL) return PCRE_ERROR_NULL;
-if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
-if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS);
-if (first_char != NULL)
-  *first_char = ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
-     ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
-return re->top_bracket;
+        const real_pcre *re = (const real_pcre *)external_re;
+        if (re == NULL)
+                return PCRE_ERROR_NULL;
+        if (re->magic_number != MAGIC_NUMBER)
+                return PCRE_ERROR_BADMAGIC;
+        if (optptr != NULL)
+                *optptr = (int)(re->options & PUBLIC_OPTIONS);
+        if (first_char != NULL)
+                *first_char = ((re->options & PCRE_FIRSTSET) != 0) ? re->first_char :
+                        ((re->options & PCRE_STARTLINE) != 0) ? -1 : -2;
+        return re->top_bracket;
 }
 
-/*************************************************
-*        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:
-  external_re      points to compiled code
-  external_study   points to study data, or NULL
-  what             what information is required
-  where            where to put the information
-
-Returns:           0 if data returned, negative on error
-*/
-
 int
-pcre_fullinfo(const pcre *external_re, const pcre_extra *study_data, int what,
-  void *where)
+pcre_fullinfo(const pcre * external_re, const pcre_extra * study_data,
+                          int what, void *where)
 {
-const real_pcre *re = (const real_pcre *)external_re;
-const real_pcre_extra *study = (const real_pcre_extra *)study_data;
-
-if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
-if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
-
-switch (what)
-  {
-  case PCRE_INFO_OPTIONS:
-  *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS;
-  break;
-
-  case PCRE_INFO_SIZE:
-  *((size_t *)where) = re->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_FIRSTCHAR:
-  *((int *)where) =
-    ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
-    ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
-  break;
-
-  case PCRE_INFO_FIRSTTABLE:
-  *((const uschar **)where) =
-    (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)?
-      study->start_bits : NULL;
-  break;
-
-  case PCRE_INFO_LASTLITERAL:
-  *((int *)where) =
-    ((re->options & PCRE_REQCHSET) != 0)? re->req_char : -1;
-  break;
+        const real_pcre *re = (const real_pcre *)external_re;
+        const real_pcre_extra *study = (const real_pcre_extra *)study_data;
 
-  default: return PCRE_ERROR_BADOPTION;
-  }
+        if (re == NULL || where == NULL)
+                return PCRE_ERROR_NULL;
+        if (re->magic_number != MAGIC_NUMBER)
+                return PCRE_ERROR_BADMAGIC;
+
+        switch (what) {
+                case PCRE_INFO_OPTIONS:
+                        *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS;
+                        break;
+
+                case PCRE_INFO_SIZE:
+                        *((size_t *) where) = re->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_FIRSTCHAR:
+                        *((int *)where) =
+                                ((re->options & PCRE_FIRSTSET) != 0) ? re->first_char :
+                                ((re->options & PCRE_STARTLINE) != 0) ? -1 : -2;
+                        break;
+
+                case PCRE_INFO_FIRSTTABLE:
+                        *((const uschar **)where) =
+                                (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0) ?
+                                study->start_bits : NULL;
+                        break;
+
+                case PCRE_INFO_LASTLITERAL:
+                        *((int *)where) =
+                                ((re->options & PCRE_REQCHSET) != 0) ? re->req_char : -1;
+                        break;
+
+                default:
+                        return PCRE_ERROR_BADOPTION;
+        }
 
-return 0;
+        return 0;
 }
 
-/*************************************************
-*            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. 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
-  errorptr   points to the pointer to the error message
-  bracount   number of previous extracting brackets
-  options    the options bits
-  isclass    TRUE if inside a character class
-  cd         pointer to char tables block
-
-Returns:     zero or positive => a data character
-             negative => a special escape sequence
-             on error, errorptr is set
-*/
-
 static int
-check_escape(const uschar **ptrptr, const char **errorptr, int bracount,
-  int options, BOOL isclass, compile_data *cd)
+check_escape(const uschar ** ptrptr, const char **errorptr, int bracount,
+                         int options, BOOL isclass, compile_data * cd)
 {
-const uschar *ptr = *ptrptr;
-int c, i;
-
-/* If backslash is at the end of the pattern, it's an error. */
-
-c = *(++ptr);
-if (c == 0) *errorptr = ERR1;
-
-/* Digits or letters may have special meaning; all others are literals. */
-
-else if (c < '0' || c > 'z') {}
-
-/* Do an initial lookup in a table. A non-zero result is something that can be
-returned immediately. Otherwise further processing may be required. */
-
-else if ((i = escapes[c - '0']) != 0) c = i;
-
-/* Escapes that need further processing, or are illegal. */
-
-else
-  {
-  const uschar *oldptr;
-  switch (c)
-    {
-    /* 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 '1': case '2': case '3': case '4': case '5':
-    case '6': case '7': case '8': case '9':
-
-    if (!isclass)
-      {
-      oldptr = ptr;
-      c -= '0';
-      while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
-        c = c * 10 + *(++ptr) - '0';
-      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) >= '8')
-      {
-      ptr--;
-      c = 0;
-      break;
-      }
-
-    /* \0 always starts an octal number, but we may drop through to here with a
-    larger first octal digit. */
-
-    case '0':
-    c -= '0';
-    while(i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 &&
-      ptr[1] != '8' && ptr[1] != '9')
-        c = c * 8 + *(++ptr) - '0';
-    c &= 255;     /* Take least significant 8 bits */
-    break;
+        const uschar *ptr = *ptrptr;
+        int c, i;
 
-    /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number
-    which can be greater than 0xff, but only if the ddd are hex digits. */
+        c = *(++ptr);
+        if (c == 0)
+                *errorptr = ERR1;
+
+        else if (c < '0' || c > 'z') {
+        }
+
+        else if ((i = escapes[c - '0']) != 0)
+                c = i;
+
+        else {
+                const uschar *oldptr;
+                switch (c) {
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                        case '8':
+                        case '9':
+
+                                if (!isclass) {
+                                        oldptr = ptr;
+                                        c -= '0';
+                                        while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
+                                                c = c * 10 + *(++ptr) - '0';
+                                        if (c < 10 || c <= bracount) {
+                                                c = -(ESC_REF + c);
+                                                break;
+                                        }
+                                        ptr = oldptr;
+                                }
+
+                                if ((c = *ptr) >= '8') {
+                                        ptr--;
+                                        c = 0;
+                                        break;
+                                }
+
+                        case '0':
+                                c -= '0';
+                                while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 &&
+                                           ptr[1] != '8' && ptr[1] != '9')
+                                        c = c * 8 + *(++ptr) - '0';
+                                c &= 255;
+                                break;
 
-    case 'x':
+                        case 'x':
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-    if (ptr[1] == '{' && (options & PCRE_UTF8) != 0)
-      {
-      const uschar *pt = ptr + 2;
-      register int count = 0;
-      c = 0;
-      while ((cd->ctypes[*pt] & ctype_xdigit) != 0)
-        {
-        count++;
-        c = c * 16 + cd->lcc[*pt] -
-          (((cd->ctypes[*pt] & ctype_digit) != 0)? '0' : 'W');
-        pt++;
-        }
-      if (*pt == '}')
-        {
-        if (c < 0 || count > 8) *errorptr = 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. */
-      }
+                                if (ptr[1] == '{' && (options & PCRE_UTF8) != 0) {
+                                        const uschar *pt = ptr + 2;
+                                        register int count = 0;
+                                        c = 0;
+                                        while ((cd->ctypes[*pt] & ctype_xdigit) != 0) {
+                                                count++;
+                                                c = c * 16 + cd->lcc[*pt] -
+                                                        (((cd->
+                                                           ctypes[*pt] & ctype_digit) != 0) ? '0' : 'W');
+                                                pt++;
+                                        }
+                                        if (*pt == '}') {
+                                                if (c < 0 || count > 8)
+                                                        *errorptr = ERR34;
+                                                ptr = pt;
+                                                break;
+                                        }
+                                }
 #endif
 
-    /* Read just a single hex char */
+                                c = 0;
+                                while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0) {
+                                        ptr++;
+                                        c = c * 16 + cd->lcc[*ptr] -
+                                                (((cd->ctypes[*ptr] & ctype_digit) != 0) ? '0' : 'W');
+                                }
+                                break;
+
+                        case 'c':
+                                c = *(++ptr);
+                                if (c == 0) {
+                                        *errorptr = ERR2;
+                                        return 0;
+                                }
+
+                                if (c >= 'a' && c <= 'z')
+                                        c = cd->fcc[c];
+                                c ^= 0x40;
+                                break;
+
+                        default:
+                                if ((options & PCRE_EXTRA) != 0)
+                                        switch (c) {
+                                                default:
+                                                        *errorptr = ERR3;
+                                                        break;
+                                        }
+                                break;
+                }
+        }
 
-    c = 0;
-    while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0)
-      {
-      ptr++;
-      c = c * 16 + cd->lcc[*ptr] -
-        (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W');
-      }
-    break;
-
-    /* Other special escapes not starting with a digit are straightforward */
-
-    case 'c':
-    c = *(++ptr);
-    if (c == 0)
-      {
-      *errorptr = ERR2;
-      return 0;
-      }
-
-    /* A letter is upper-cased; then the 0x40 bit is flipped */
-
-    if (c >= 'a' && c <= 'z') c = cd->fcc[c];
-    c ^= 0x40;
-    break;
-
-    /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
-    other alphameric 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:
-      *errorptr = ERR3;
-      break;
-      }
-    break;
-    }
-  }
-
-*ptrptr = ptr;
-return c;
+        *ptrptr = ptr;
+        return c;
 }
 
-/*************************************************
-*            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 '{'
-  cd        pointer to char tables block
-
-Returns:    TRUE or FALSE
-*/
-
-static BOOL
-is_counted_repeat(const uschar *p, compile_data *cd)
+static BOOL is_counted_repeat(const uschar * p, compile_data * cd)
 {
-if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
-while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
-if (*p == '}') return TRUE;
-
-if (*p++ != ',') return FALSE;
-if (*p == '}') return TRUE;
-
-if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
-while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
-return (*p == '}');
+        if ((cd->ctypes[*p++] & ctype_digit) == 0)
+                return FALSE;
+        while ((cd->ctypes[*p] & ctype_digit) != 0)
+                p++;
+        if (*p == '}')
+                return TRUE;
+
+        if (*p++ != ',')
+                return FALSE;
+        if (*p == '}')
+                return TRUE;
+
+        if ((cd->ctypes[*p++] & ctype_digit) == 0)
+                return FALSE;
+        while ((cd->ctypes[*p] & ctype_digit) != 0)
+                p++;
+        return (*p == '}');
 }
 
-/*************************************************
-*         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
-  errorptr   points to pointer to error message
-  cd         pointer to character tables clock
-
-Returns:     pointer to '}' on success;
-             current ptr on error, with errorptr set
-*/
-
-static const uschar *
-read_repeat_counts(const uschar *p, int *minp, int *maxp,
-  const char **errorptr, compile_data *cd)
+static const uschar *read_repeat_counts(const uschar * p, int *minp,
+                                                                                int *maxp, const char **errorptr,
+                                                                                compile_data * cd)
 {
-int min = 0;
-int max = -1;
-
-while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0';
-
-if (*p == '}') max = min; else
-  {
-  if (*(++p) != '}')
-    {
-    max = 0;
-    while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0';
-    if (max < min)
-      {
-      *errorptr = ERR4;
-      return p;
-      }
-    }
-  }
+        int min = 0;
+        int max = -1;
 
-/* Do paranoid checks, then fill in the required variables, and pass back the
-pointer to the terminating '}'. */
+        while ((cd->ctypes[*p] & ctype_digit) != 0)
+                min = min * 10 + *p++ - '0';
 
-if (min > 65535 || max > 65535)
-  *errorptr = ERR5;
-else
-  {
-  *minp = min;
-  *maxp = max;
-  }
-return p;
+        if (*p == '}')
+                max = min;
+        else {
+                if (*(++p) != '}') {
+                        max = 0;
+                        while ((cd->ctypes[*p] & ctype_digit) != 0)
+                                max = max * 10 + *p++ - '0';
+                        if (max < min) {
+                                *errorptr = ERR4;
+                                return p;
+                        }
+                }
+        }
+
+        if (min > 65535 || max > 65535)
+                *errorptr = ERR5;
+        else {
+                *minp = min;
+                *maxp = max;
+        }
+        return p;
 }
 
-/*************************************************
-*        Find the fixed length of a pattern      *
-*************************************************/
-
-/* Scan a pattern and compute the fixed length of subject that will match it,
-if the length is fixed. This is needed for dealing with backward assertions.
-
-Arguments:
-  code     points to the start of the pattern (the bracket)
-  options  the compiling options
-
-Returns:   the fixed length, or -1 if there is no fixed length
-*/
-
-static int
-find_fixedlength(uschar *code, int options)
+static int find_fixedlength(uschar * code, int options)
 {
-int length = -1;
-
-register int branchlength = 0;
-register uschar *cc = code + 3;
+        int length = -1;
 
-/* Scan along the opcodes for this branch. If we get to the end of the
-branch, check the length against that of the other branches. */
+        register int branchlength = 0;
+        register uschar *cc = code + 3;
 
-for (;;)
-  {
-  int d;
-  register int op = *cc;
-  if (op >= OP_BRA) op = OP_BRA;
-
-  switch (op)
-    {
-    case OP_BRA:
-    case OP_ONCE:
-    case OP_COND:
-    d = find_fixedlength(cc, options);
-    if (d < 0) return -1;
-    branchlength += d;
-    do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
-    cc += 3;
-    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 += 3;
-    branchlength = 0;
-    break;
-
-    /* Skip over assertive subpatterns */
-
-    case OP_ASSERT:
-    case OP_ASSERT_NOT:
-    case OP_ASSERTBACK:
-    case OP_ASSERTBACK_NOT:
-    do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
-    cc += 3;
-    break;
-
-    /* Skip over things that don't match chars */
-
-    case OP_REVERSE:
-    case OP_BRANUMBER:
-    case OP_CREF:
-    cc++;
-    /* Fall through */
-
-    case OP_OPT:
-    cc++;
-    /* Fall through */
-
-    case OP_SOD:
-    case OP_EOD:
-    case OP_EODN:
-    case OP_CIRC:
-    case OP_DOLL:
-    case OP_NOT_WORD_BOUNDARY:
-    case OP_WORD_BOUNDARY:
-    cc++;
-    break;
-
-    /* Handle char strings. In UTF-8 mode we must count characters, not bytes.
-    This requires a scan of the string, unfortunately. We assume valid UTF-8
-    strings, so all we do is reduce the length by one for byte whose bits are
-    10xxxxxx. */
+        for (;;) {
+                int d;
+                register int op = *cc;
+                if (op >= OP_BRA)
+                        op = OP_BRA;
+
+                switch (op) {
+                        case OP_BRA:
+                        case OP_ONCE:
+                        case OP_COND:
+                                d = find_fixedlength(cc, options);
+                                if (d < 0)
+                                        return -1;
+                                branchlength += d;
+                                do
+                                        cc += (cc[1] << 8) + cc[2];
+                                while (*cc == OP_ALT);
+                                cc += 3;
+                                break;
+
+                        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 += 3;
+                                branchlength = 0;
+                                break;
+
+                        case OP_ASSERT:
+                        case OP_ASSERT_NOT:
+                        case OP_ASSERTBACK:
+                        case OP_ASSERTBACK_NOT:
+                                do
+                                        cc += (cc[1] << 8) + cc[2];
+                                while (*cc == OP_ALT);
+                                cc += 3;
+                                break;
+
+                        case OP_REVERSE:
+                        case OP_BRANUMBER:
+                        case OP_CREF:
+                                cc++;
+                        case OP_OPT:
+                                cc++;
+                        case OP_SOD:
+                        case OP_EOD:
+                        case OP_EODN:
+                        case OP_CIRC:
+                        case OP_DOLL:
+                        case OP_NOT_WORD_BOUNDARY:
+                        case OP_WORD_BOUNDARY:
+                                cc++;
+                                break;
 
-    case OP_CHARS:
-    branchlength += *(++cc);
+                        case OP_CHARS:
+                                branchlength += *(++cc);
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-    for (d = 1; d <= *cc; d++)
-      if ((cc[d] & 0xc0) == 0x80) branchlength--;
+                                for (d = 1; d <= *cc; d++)
+                                        if ((cc[d] & 0xc0) == 0x80)
+                                                branchlength--;
 #endif
-    cc += *cc + 1;
-    break;
+                                cc += *cc + 1;
+                                break;
 
-    /* Handle exact repetitions */
-
-    case OP_EXACT:
-    case OP_TYPEEXACT:
-    branchlength += (cc[1] << 8) + cc[2];
-    cc += 4;
-    break;
-
-    /* Handle single-char matchers */
-
-    case OP_NOT_DIGIT:
-    case OP_DIGIT:
-    case OP_NOT_WHITESPACE:
-    case OP_WHITESPACE:
-    case OP_NOT_WORDCHAR:
-    case OP_WORDCHAR:
-    case OP_ANY:
-    branchlength++;
-    cc++;
-    break;
-
-    /* Check a class for variable quantification */
-
-    case OP_CLASS:
-    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 ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4]) return -1;
-      branchlength += (cc[1] << 8) + cc[2];
-      cc += 5;
-      break;
-
-      default:
-      branchlength++;
-      }
-    break;
-
-    /* Anything else is variable length */
-
-    default:
-    return -1;
-    }
-  }
-/* Control never gets here */
+                        case OP_EXACT:
+                        case OP_TYPEEXACT:
+                                branchlength += (cc[1] << 8) + cc[2];
+                                cc += 4;
+                                break;
+
+                        case OP_NOT_DIGIT:
+                        case OP_DIGIT:
+                        case OP_NOT_WHITESPACE:
+                        case OP_WHITESPACE:
+                        case OP_NOT_WORDCHAR:
+                        case OP_WORDCHAR:
+                        case OP_ANY:
+                                branchlength++;
+                                cc++;
+                                break;
+
+                        case OP_CLASS:
+                                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 ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4])
+                                                        return -1;
+                                                branchlength += (cc[1] << 8) + cc[2];
+                                                cc += 5;
+                                                break;
+
+                                        default:
+                                                branchlength++;
+                                }
+                                break;
+
+                        default:
+                                return -1;
+                }
+        }
 }
 
-/*************************************************
-*           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 an
-optional ^ and then a sequence of letters, terminated by a matching ":]" or
-".]" or "=]".
-
-Argument:
-  ptr      pointer to the initial [
-  endptr   where to return the end pointer
-  cd       pointer to compile data
-
-Returns:   TRUE or FALSE
-*/
-
 static BOOL
-check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd)
+check_posix_syntax(const uschar * ptr, const uschar ** endptr,
+                                   compile_data * cd)
 {
-int terminator;          /* Don't combine these lines; the Solaris cc */
-terminator = *(++ptr);   /* compiler warns about "non-constant" initializer. */
-if (*(++ptr) == '^') ptr++;
-while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
-if (*ptr == terminator && ptr[1] == ']')
-  {
-  *endptr = ptr;
-  return TRUE;
-  }
-return FALSE;
+        int terminator;
+        terminator = *(++ptr);
+        if (*(++ptr) == '^')
+                ptr++;
+        while ((cd->ctypes[*ptr] & ctype_letter) != 0)
+                ptr++;
+        if (*ptr == terminator && ptr[1] == ']') {
+                *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)
+static int check_posix_name(const uschar * ptr, int len)
 {
-register int yield = 0;
-while (posix_name_lengths[yield] != 0)
-  {
-  if (len == posix_name_lengths[yield] &&
-    strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
-  yield++;
-  }
-return -1;
+        register int yield = 0;
+        while (posix_name_lengths[yield] != 0) {
+                if (len == posix_name_lengths[yield] &&
+                        strncmp((const char *)ptr, posix_names[yield], len) == 0)
+                        return yield;
+                yield++;
+        }
+        return -1;
 }
 
-/*************************************************
-*           Compile one branch                   *
-*************************************************/
-
-/* Scan the pattern, compiling it into the code vector.
-
-Arguments:
-  options      the option bits
-  brackets     points to number of extracting brackets used
-  code         points to the pointer to the current code point
-  ptrptr       points to the current pattern pointer
-  errorptr     points to pointer to error message
-  optchanged   set to the value of the last OP_OPT item compiled
-  reqchar      set to the last literal character required, else -1
-  countlits    set to count of mandatory literal characters
-  cd           contains pointers to tables
-
-Returns:       TRUE on success
-               FALSE, with *errorptr set on error
-*/
-
 static BOOL
-compile_branch(int options, int *brackets, uschar **codeptr,
-  const uschar **ptrptr, const char **errorptr, int *optchanged,
-  int *reqchar, int *countlits, compile_data *cd)
+compile_branch(int options, int *brackets, uschar ** codeptr,
+                           const uschar ** ptrptr, const char **errorptr, int *optchanged,
+                           int *reqchar, int *countlits, compile_data * cd)
 {
-int repeat_type, op_type;
-int repeat_min, repeat_max;
-int bravalue, length;
-int greedy_default, greedy_non_default;
-int prevreqchar;
-int condcount = 0;
-int subcountlits = 0;
-register int c;
-register uschar *code = *codeptr;
-uschar *tempcode;
-const uschar *ptr = *ptrptr;
-const uschar *tempptr;
-uschar *previous = NULL;
-uschar class[32];
-
-/* Set up the default and non-default settings for greediness */
-
-greedy_default = ((options & PCRE_UNGREEDY) != 0);
-greedy_non_default = greedy_default ^ 1;
-
-/* Initialize no required char, and count of literals */
-
-*reqchar = prevreqchar = -1;
-*countlits = 0;
-
-/* Switch on next character until the end of the branch */
-
-for (;; ptr++)
-  {
-  BOOL negate_class;
-  int class_charcount;
-  int class_lastchar;
-  int newoptions;
-  int skipbytes;
-  int subreqchar;
-
-  c = *ptr;
-  if ((options & PCRE_EXTENDED) != 0)
-    {
-    if ((cd->ctypes[c] & ctype_space) != 0) continue;
-    if (c == '#')
-      {
-      /* The space before the ; is to avoid a warning on a silly compiler
-      on the Macintosh. */
-      while ((c = *(++ptr)) != 0 && c != '\n') ;
-      continue;
-      }
-    }
-
-  switch(c)
-    {
-    /* The branch terminates at end of string, |, or ). */
-
-    case 0:
-    case '|':
-    case ')':
-    *codeptr = code;
-    *ptrptr = ptr;
-    return TRUE;
-
-    /* Handle single-character metacharacters */
-
-    case '^':
-    previous = NULL;
-    *code++ = OP_CIRC;
-    break;
-
-    case '$':
-    previous = NULL;
-    *code++ = OP_DOLL;
-    break;
-
-    case '.':
-    previous = code;
-    *code++ = OP_ANY;
-    break;
-
-    /* Character classes. These always build a 32-byte bitmap of the permitted
-    characters, except in the special case where there is only one character.
-    For negated classes, we build the map as usual, then invert it at the end.
-    */
-
-    case '[':
-    previous = code;
-    *code++ = OP_CLASS;
-
-    /* If the first character is '^', set the negation flag and skip it. */
-
-    if ((c = *(++ptr)) == '^')
-      {
-      negate_class = TRUE;
-      c = *(++ptr);
-      }
-    else negate_class = FALSE;
-
-    /* Keep a count of chars so that we can optimize the case of just a single
-    character. */
-
-    class_charcount = 0;
-    class_lastchar = -1;
-
-    /* Initialize the 32-char bit map to all zeros. We have to build the
-    map in a temporary bit of store, in case the class contains only 1
-    character, because in that case the compiled code doesn't use the
-    bit map. */
-
-    memset(class, 0, 32 * sizeof(uschar));
-
-    /* Process characters until ] is reached. By writing this as a "do" it
-    means that an initial ] is taken as a data character. */
-
-    do
-      {
-      if (c == 0)
-        {
-        *errorptr = ERR6;
-        goto FAILED;
-        }
-
-      /* 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 does. */
-
-      if (c == '[' &&
-          (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
-          check_posix_syntax(ptr, &tempptr, cd))
-        {
-        BOOL local_negate = FALSE;
-        int posix_class, i;
-        register const uschar *cbits = cd->cbits;
-
-        if (ptr[1] != ':')
-          {
-          *errorptr = ERR31;
-          goto FAILED;
-          }
-
-        ptr += 2;
-        if (*ptr == '^')
-          {
-          local_negate = TRUE;
-          ptr++;
-          }
-
-        posix_class = check_posix_name(ptr, tempptr - ptr);
-        if (posix_class < 0)
-          {
-          *errorptr = 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;
-
-        /* Or into the map we are building up to 3 of the static class
-        tables, or their negations. */
-
-        posix_class *= 3;
-        for (i = 0; i < 3; i++)
-          {
-          int taboffset = posix_class_maps[posix_class + i];
-          if (taboffset < 0) break;
-          if (local_negate)
-            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset];
-          else
-            for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset];
-          }
-
-        ptr = tempptr + 1;
-        class_charcount = 10;  /* Set > 1; assumes more than 1 per class */
-        continue;
-        }
-
-      /* Backslash may introduce a single character, or it may introduce one
-      of the specials, which just set a flag. Escaped items are checked for
-      validity in the pre-compiling pass. The sequence \b is a special case.
-      Inside a class (and only there) it is treated as backspace. Elsewhere
-      it marks a word boundary. Other escapes have preset maps ready to
-      or into the one we are building. We assume they have more than one
-      character in them, so set class_count bigger than one. */
-
-      if (c == '\\')
-        {
-        c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
-        if (-c == ESC_b) c = '\b';
-        else if (c < 0)
-          {
-          register const uschar *cbits = cd->cbits;
-          class_charcount = 10;
-          switch (-c)
-            {
-            case ESC_d:
-            for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit];
-            continue;
-
-            case ESC_D:
-            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit];
-            continue;
-
-            case ESC_w:
-            for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word];
-            continue;
-
-            case ESC_W:
-            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word];
-            continue;
-
-            case ESC_s:
-            for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space];
-            continue;
-
-            case ESC_S:
-            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space];
-            continue;
-
-            default:
-            *errorptr = ERR7;
-            goto FAILED;
-            }
-          }
-
-        /* Fall through if single character, but don't at present allow
-        chars > 255 in UTF-8 mode. */
+        int repeat_type, op_type;
+        int repeat_min, repeat_max;
+        int bravalue, length;
+        int greedy_default, greedy_non_default;
+        int prevreqchar;
+        int condcount = 0;
+        int subcountlits = 0;
+        register int c;
+        register uschar *code = *codeptr;
+        uschar *tempcode;
+        const uschar *ptr = *ptrptr;
+        const uschar *tempptr;
+        uschar *previous = NULL;
+        uschar class[32];
+
+        greedy_default = ((options & PCRE_UNGREEDY) != 0);
+        greedy_non_default = greedy_default ^ 1;
+
+        *reqchar = prevreqchar = -1;
+        *countlits = 0;
+
+        for (;; ptr++) {
+                BOOL negate_class;
+                int class_charcount;
+                int class_lastchar;
+                int newoptions;
+                int skipbytes;
+                int subreqchar;
+
+                c = *ptr;
+                if ((options & PCRE_EXTENDED) != 0) {
+                        if ((cd->ctypes[c] & ctype_space) != 0)
+                                continue;
+                        if (c == '#') {
+                                while ((c = *(++ptr)) != 0 && c != '\n') ;
+                                continue;
+                        }
+                }
+
+                switch (c) {
+                        case 0:
+                        case '|':
+                        case ')':
+                                *codeptr = code;
+                                *ptrptr = ptr;
+                                return TRUE;
+
+                        case '^':
+                                previous = NULL;
+                                *code++ = OP_CIRC;
+                                break;
+
+                        case '$':
+                                previous = NULL;
+                                *code++ = OP_DOLL;
+                                break;
+
+                        case '.':
+                                previous = code;
+                                *code++ = OP_ANY;
+                                break;
+
+                        case '[':
+                                previous = code;
+                                *code++ = OP_CLASS;
+
+                                if ((c = *(++ptr)) == '^') {
+                                        negate_class = TRUE;
+                                        c = *(++ptr);
+                                }
+                                else
+                                        negate_class = FALSE;
+
+                                class_charcount = 0;
+                                class_lastchar = -1;
+
+                                memset(class, 0, 32 * sizeof (uschar));
+
+                                do {
+                                        if (c == 0) {
+                                                *errorptr = ERR6;
+                                                goto FAILED;
+                                        }
+
+                                        if (c == '[' &&
+                                                (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
+                                                check_posix_syntax(ptr, &tempptr, cd)) {
+                                                BOOL local_negate = FALSE;
+                                                int posix_class, i;
+                                                register const uschar *cbits = cd->cbits;
+
+                                                if (ptr[1] != ':') {
+                                                        *errorptr = ERR31;
+                                                        goto FAILED;
+                                                }
+
+                                                ptr += 2;
+                                                if (*ptr == '^') {
+                                                        local_negate = TRUE;
+                                                        ptr++;
+                                                }
+
+                                                posix_class = check_posix_name(ptr, tempptr - ptr);
+                                                if (posix_class < 0) {
+                                                        *errorptr = ERR30;
+                                                        goto FAILED;
+                                                }
+
+                                                if ((options & PCRE_CASELESS) != 0
+                                                        && posix_class <= 2) posix_class = 0;
+
+                                                posix_class *= 3;
+                                                for (i = 0; i < 3; i++) {
+                                                        int taboffset = posix_class_maps[posix_class + i];
+                                                        if (taboffset < 0)
+                                                                break;
+                                                        if (local_negate)
+                                                                for (c = 0; c < 32; c++)
+                                                                        class[c] |= ~cbits[c + taboffset];
+                                                        else
+                                                                for (c = 0; c < 32; c++)
+                                                                        class[c] |= cbits[c + taboffset];
+                                                }
+
+                                                ptr = tempptr + 1;
+                                                class_charcount = 10;
+                                                continue;
+                                        }
+
+                                        if (c == '\\') {
+                                                c =
+                                                        check_escape(&ptr, errorptr, *brackets, options,
+                                                                                 TRUE, cd);
+                                                if (-c == ESC_b)
+                                                        c = '\b';
+                                                else if (c < 0) {
+                                                        register const uschar *cbits = cd->cbits;
+                                                        class_charcount = 10;
+                                                        switch (-c) {
+                                                                case ESC_d:
+                                                                        for (c = 0; c < 32; c++)
+                                                                                class[c] |= cbits[c + cbit_digit];
+                                                                        continue;
+
+                                                                case ESC_D:
+                                                                        for (c = 0; c < 32; c++)
+                                                                                class[c] |= ~cbits[c + cbit_digit];
+                                                                        continue;
+
+                                                                case ESC_w:
+                                                                        for (c = 0; c < 32; c++)
+                                                                                class[c] |= cbits[c + cbit_word];
+                                                                        continue;
+
+                                                                case ESC_W:
+                                                                        for (c = 0; c < 32; c++)
+                                                                                class[c] |= ~cbits[c + cbit_word];
+                                                                        continue;
+
+                                                                case ESC_s:
+                                                                        for (c = 0; c < 32; c++)
+                                                                                class[c] |= cbits[c + cbit_space];
+                                                                        continue;
+
+                                                                case ESC_S:
+                                                                        for (c = 0; c < 32; c++)
+                                                                                class[c] |= ~cbits[c + cbit_space];
+                                                                        continue;
+
+                                                                default:
+                                                                        *errorptr = ERR7;
+                                                                        goto FAILED;
+                                                        }
+                                                }
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-        if (c > 255)
-          {
-          *errorptr = ERR33;
-          goto FAILED;
-          }
+                                                if (c > 255) {
+                                                        *errorptr = ERR33;
+                                                        goto FAILED;
+                                                }
 #endif
-        }
+                                        }
 
-      /* 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
-      here is treated as a literal. */
-
-      if (ptr[1] == '-' && ptr[2] != ']')
-        {
-        int d;
-        ptr += 2;
-        d = *ptr;
-
-        if (d == 0)
-          {
-          *errorptr = ERR6;
-          goto FAILED;
-          }
-
-        /* 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 (d == '\\')
-          {
-          const uschar *oldptr = ptr;
-          d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
+                                        if (ptr[1] == '-' && ptr[2] != ']') {
+                                                int d;
+                                                ptr += 2;
+                                                d = *ptr;
+
+                                                if (d == 0) {
+                                                        *errorptr = ERR6;
+                                                        goto FAILED;
+                                                }
+
+                                                if (d == '\\') {
+                                                        const uschar *oldptr = ptr;
+                                                        d =
+                                                                check_escape(&ptr, errorptr, *brackets,
+                                                                                         options, TRUE, cd);
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-          if (d > 255)
-            {
-            *errorptr = ERR33;
-            goto FAILED;
-            }
+                                                        if (d > 255) {
+                                                                *errorptr = ERR33;
+                                                                goto FAILED;
+                                                        }
 #endif
-          /* \b is backslash; any other special means the '-' was literal */
-
-          if (d < 0)
-            {
-            if (d == -ESC_b) d = '\b'; else
-              {
-              ptr = oldptr - 2;
-              goto SINGLE_CHARACTER;  /* A few lines below */
-              }
-            }
-          }
-
-        if (d < c)
-          {
-          *errorptr = ERR8;
-          goto FAILED;
-          }
-
-        for (; c <= d; c++)
-          {
-          class[c/8] |= (1 << (c&7));
-          if ((options & PCRE_CASELESS) != 0)
-            {
-            int uc = cd->fcc[c];           /* flip case */
-            class[uc/8] |= (1 << (uc&7));
-            }
-          class_charcount++;                /* in case a one-char range */
-          class_lastchar = c;
-          }
-        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. */
-
-      SINGLE_CHARACTER:
-
-      class [c/8] |= (1 << (c&7));
-      if ((options & PCRE_CASELESS) != 0)
-        {
-        c = cd->fcc[c];   /* flip case */
-        class[c/8] |= (1 << (c&7));
-        }
-      class_charcount++;
-      class_lastchar = c;
-      }
-
-    /* Loop until ']' reached; the check for end of string happens inside the
-    loop. This "while" is the end of the "do" above. */
-
-    while ((c = *(++ptr)) != ']');
-
-    /* If class_charcount is 1 and class_lastchar is not negative, we saw
-    precisely one character. This doesn't need the whole 32-byte bit map.
-    We turn it into a 1-character OP_CHAR if it's positive, or OP_NOT if
-    it's negative. */
-
-    if (class_charcount == 1 && class_lastchar >= 0)
-      {
-      if (negate_class)
-        {
-        code[-1] = OP_NOT;
-        }
-      else
-        {
-        code[-1] = OP_CHARS;
-        *code++ = 1;
-        }
-      *code++ = class_lastchar;
-      }
-
-    /* Otherwise, negate the 32-byte map if necessary, and copy it into
-    the code vector. */
-
-    else
-      {
-      if (negate_class)
-        for (c = 0; c < 32; c++) code[c] = ~class[c];
-      else
-        memcpy(code, class, 32);
-      code += 32;
-      }
-    break;
-
-    /* Various kinds of repeat */
-
-    case '{':
-    if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR;
-    ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd);
-    if (*errorptr != NULL) goto FAILED;
-    goto REPEAT;
-
-    case '*':
-    repeat_min = 0;
-    repeat_max = -1;
-    goto REPEAT;
-
-    case '+':
-    repeat_min = 1;
-    repeat_max = -1;
-    goto REPEAT;
-
-    case '?':
-    repeat_min = 0;
-    repeat_max = 1;
-
-    REPEAT:
-    if (previous == NULL)
-      {
-      *errorptr = ERR9;
-      goto FAILED;
-      }
-
-    /* If the next character is '?' this is a minimizing repeat, by default,
-    but if PCRE_UNGREEDY is set, it works the other way round. Advance to the
-    next character. */
-
-    if (ptr[1] == '?')
-      { repeat_type = greedy_non_default; ptr++; }
-    else repeat_type = greedy_default;
-
-    /* If previous was a string of characters, chop off the last one and use it
-    as the subject of the repeat. If there was only one character, we can
-    abolish the previous item altogether. A repeat with a zero minimum wipes
-    out any reqchar setting, backing up to the previous value. We must also
-    adjust the countlits value. */
-
-    if (*previous == OP_CHARS)
-      {
-      int len = previous[1];
-
-      if (repeat_min == 0) *reqchar = prevreqchar;
-      *countlits += repeat_min - 1;
-
-      if (len == 1)
-        {
-        c = previous[2];
-        code = previous;
-        }
-      else
-        {
-        c = previous[len+1];
-        previous[1]--;
-        code--;
-        }
-      op_type = 0;                 /* Use single-char op codes */
-      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 adding a suitable offset into repeat_type. */
-
-    else if ((int)*previous == OP_NOT)
-      {
-      op_type = OP_NOTSTAR - OP_STAR;  /* Use "not" opcodes */
-      c = previous[1];
-      code = previous;
-      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 adding a suitable offset into repeat_type. */
-
-    else if ((int)*previous < OP_EODN || *previous == OP_ANY)
-      {
-      op_type = OP_TYPESTAR - OP_STAR;  /* Use type opcodes */
-      c = *previous;
-      code = previous;
-
-      OUTPUT_SINGLE_REPEAT:
-
-      /* If the maximum is zero then the minimum must also be zero; Perl allows
-      this case, so we do too - by simply omitting the item altogether. */
-
-      if (repeat_max == 0) goto END_REPEAT;
-
-      /* Combine the op_type with the repeat_type */
-
-      repeat_type += op_type;
-
-      /* A minimum of zero is handled either as the special case * or ?, or as
-      an UPTO, with the maximum given. */
-
-      if (repeat_min == 0)
-        {
-        if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
-          else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
-        else
-          {
-          *code++ = OP_UPTO + repeat_type;
-          *code++ = repeat_max >> 8;
-          *code++ = (repeat_max & 255);
-          }
-        }
-
-      /* The case {1,} is handled as the special case + */
-
-      else if (repeat_min == 1 && repeat_max == -1)
-        *code++ = OP_PLUS + repeat_type;
-
-      /* The case {n,n} is just an EXACT, while the general case {n,m} is
-      handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */
-
-      else
-        {
-        if (repeat_min != 1)
-          {
-          *code++ = OP_EXACT + op_type;  /* NB EXACT doesn't have repeat_type */
-          *code++ = repeat_min >> 8;
-          *code++ = (repeat_min & 255);
-          }
-
-        /* If the mininum is 1 and the previous item was a character string,
-        we either have to put back the item that got cancelled if the string
-        length was 1, or add the character back onto the end of a longer
-        string. For a character type nothing need be done; it will just get
-        put back naturally. Note that the final character is always going to
-        get added below. */
-
-        else if (*previous == OP_CHARS)
-          {
-          if (code == previous) code += 2; else previous[1]++;
-          }
-
-        /*  For a single negated character we also have to put back the
-        item that got cancelled. */
-
-        else if (*previous == OP_NOT) code++;
-
-        /* If the maximum is unlimited, insert an OP_STAR. */
-
-        if (repeat_max < 0)
-          {
-          *code++ = c;
-          *code++ = OP_STAR + repeat_type;
-          }
-
-        /* Else insert an UPTO if the max is greater than the min. */
-
-        else if (repeat_max != repeat_min)
-          {
-          *code++ = c;
-          repeat_max -= repeat_min;
-          *code++ = OP_UPTO + repeat_type;
-          *code++ = repeat_max >> 8;
-          *code++ = (repeat_max & 255);
-          }
-        }
-
-      /* The character or character type itself comes last in all cases. */
-
-      *code++ = c;
-      }
-
-    /* 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_REF)
-      {
-      if (repeat_max == 0)
-        {
-        code = previous;
-        goto END_REPEAT;
-        }
-      if (repeat_min == 0 && repeat_max == -1)
-        *code++ = OP_CRSTAR + repeat_type;
-      else if (repeat_min == 1 && repeat_max == -1)
-        *code++ = OP_CRPLUS + repeat_type;
-      else if (repeat_min == 0 && repeat_max == 1)
-        *code++ = OP_CRQUERY + repeat_type;
-      else
-        {
-        *code++ = OP_CRRANGE + repeat_type;
-        *code++ = repeat_min >> 8;
-        *code++ = repeat_min & 255;
-        if (repeat_max == -1) repeat_max = 0;  /* 2-byte encoding for max */
-        *code++ = repeat_max >> 8;
-        *code++ = repeat_max & 255;
-        }
-      }
-
-    /* If previous was a bracket group, we may have to replicate it in certain
-    cases. */
-
-    else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE ||
-             (int)*previous == OP_COND)
-      {
-      register int i;
-      int ketoffset = 0;
-      int len = code - previous;
-      uschar *bralink = NULL;
-
-      /* 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 += (ket[1] << 8) + ket[2]; while (*ket != OP_KET);
-        ketoffset = 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 we set up a required char from the bracket, we must back off
-        to the previous value and reset the countlits value too. */
-
-        if (subcountlits > 0)
-          {
-          *reqchar = prevreqchar;
-          *countlits -= subcountlits;
-          }
-
-        /* If the maximum is also zero, we just omit the group from the output
-        altogether. */
-
-        if (repeat_max == 0)
-          {
-          code = previous;
-          goto END_REPEAT;
-          }
-
-        /* If the maximum is 1 or unlimited, we just have to stick in the
-        BRAZERO and do no more at this point. */
-
-        if (repeat_max <= 1)
-          {
-          memmove(previous+1, previous, len);
-          code++;
-          *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 just have to
-        adjust the value or repeat_max, since one less copy is required. */
-
-        else
-          {
-          int offset;
-          memmove(previous+4, previous, len);
-          code += 4;
-          *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 : previous - bralink;
-          bralink = previous;
-          *previous++ = offset >> 8;
-          *previous++ = offset & 255;
-          }
-
-        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. */
-
-      else
-        {
-        for (i = 1; i < repeat_min; i++)
-          {
-          memcpy(code, previous, len);
-          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. */
-
-      if (repeat_max >= 0)
-        {
-        for (i = repeat_max - 1; i >= 0; i--)
-          {
-          *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 : code - bralink;
-            bralink = code;
-            *code++ = offset >> 8;
-            *code++ = offset & 255;
-            }
-
-          memcpy(code, previous, len);
-          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 = code - bralink + 1;
-          uschar *bra = code - offset;
-          oldlinkoffset = (bra[1] << 8) + bra[2];
-          bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
-          *code++ = OP_KET;
-          *code++ = bra[1] = offset >> 8;
-          *code++ = bra[2] = (offset & 255);
-          }
-        }
-
-      /* 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. */
-
-      else code[-ketoffset] = OP_KETRMAX + repeat_type;
-      }
-
-    /* Else there's some kind of shambles */
-
-    else
-      {
-      *errorptr = ERR11;
-      goto FAILED;
-      }
-
-    /* In all case we no longer have a previous item. */
-
-    END_REPEAT:
-    previous = NULL;
-    break;
-
-    /* Start of nested bracket sub-expression, or comment or lookahead or
-    lookbehind or option setting or condition. First deal with special things
-    that can come after a bracket; all are introduced by ?, and the appearance
-    of any of them means that this is not a referencing group. They were
-    checked for validity in the first pass over the string, so we don't have to
-    check for syntax errors here.  */
-
-    case '(':
-    newoptions = options;
-    skipbytes = 0;
-
-    if (*(++ptr) == '?')
-      {
-      int set, unset;
-      int *optset;
-
-      switch (*(++ptr))
-        {
-        case '#':                 /* Comment; skip to ket */
-        ptr++;
-        while (*ptr != ')') ptr++;
-        continue;
-
-        case ':':                 /* Non-extracting bracket */
-        bravalue = OP_BRA;
-        ptr++;
-        break;
-
-        case '(':
-        bravalue = OP_COND;       /* Conditional group */
-        if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0)
-          {
-          int condref = *ptr - '0';
-          while (*(++ptr) != ')') condref = condref*10 + *ptr - '0';
-          if (condref == 0)
-            {
-            *errorptr = ERR35;
-            goto FAILED;
-            }
-          ptr++;
-          code[3] = OP_CREF;
-          code[4] = condref >> 8;
-          code[5] = condref & 255;
-          skipbytes = 3;
-          }
-        else ptr--;
-        break;
-
-        case '=':                 /* Positive lookahead */
-        bravalue = OP_ASSERT;
-        ptr++;
-        break;
-
-        case '!':                 /* Negative lookahead */
-        bravalue = OP_ASSERT_NOT;
-        ptr++;
-        break;
-
-        case '<':                 /* Lookbehinds */
-        switch (*(++ptr))
-          {
-          case '=':               /* Positive lookbehind */
-          bravalue = OP_ASSERTBACK;
-          ptr++;
-          break;
-
-          case '!':               /* Negative lookbehind */
-          bravalue = OP_ASSERTBACK_NOT;
-          ptr++;
-          break;
-
-          default:                /* Syntax error */
-          *errorptr = ERR24;
-          goto FAILED;
-          }
-        break;
-
-        case '>':                 /* One-time brackets */
-        bravalue = OP_ONCE;
-        ptr++;
-        break;
-
-        case 'R':                 /* Pattern recursion */
-        *code++ = OP_RECURSE;
-        ptr++;
-        continue;
-
-        default:                  /* Option setting */
-        set = unset = 0;
-        optset = &set;
-
-        while (*ptr != ')' && *ptr != ':')
-          {
-          switch (*ptr++)
-            {
-            case '-': optset = &unset; break;
-
-            case 'i': *optset |= PCRE_CASELESS; break;
-            case 'm': *optset |= PCRE_MULTILINE; break;
-            case 's': *optset |= PCRE_DOTALL; break;
-            case 'x': *optset |= PCRE_EXTENDED; break;
-            case 'U': *optset |= PCRE_UNGREEDY; break;
-            case 'X': *optset |= PCRE_EXTRA; break;
-
-            default:
-            *errorptr = ERR12;
-            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. At top
-        level there is nothing else to be done (the options will in fact have
-        been set from the start of compiling as a result of the first pass) but
-        at an inner level we must compile code to change the ims options if
-        necessary, and pass the new setting back so that it can be put at the
-        start of any following branches, and when this group ends, a resetting
-        item can be compiled. */
-
-        if (*ptr == ')')
-          {
-          if ((options & PCRE_INGROUP) != 0 &&
-              (options & PCRE_IMS) != (newoptions & PCRE_IMS))
-            {
-            *code++ = OP_OPT;
-            *code++ = *optchanged = newoptions & PCRE_IMS;
-            }
-          options = newoptions;  /* Change options at this level */
-          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++;
-        }
-      }
-
-    /* Else we have a referencing group; adjust the opcode. If the bracket
-    number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and
-    arrange for the true number to follow later, in an OP_BRANUMBER item. */
-
-    else
-      {
-      if (++(*brackets) > EXTRACT_BASIC_MAX)
-        {
-        bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
-        code[3] = OP_BRANUMBER;
-        code[4] = *brackets >> 8;
-        code[5] = *brackets & 255;
-        skipbytes = 3;
-        }
-      else bravalue = OP_BRA + *brackets;
-      }
-
-    /* Process nested bracketed re. Assertions may not be repeated, but other
-    kinds can be. 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;
-
-    if (!compile_regex(
-         options | PCRE_INGROUP,       /* Set for all nested groups */
-         ((options & PCRE_IMS) != (newoptions & PCRE_IMS))?
-           newoptions & PCRE_IMS : -1, /* Pass ims options if changed */
-         brackets,                     /* Extracting bracket count */
-         &tempcode,                    /* Where to put code (updated) */
-         &ptr,                         /* Input pointer (updated) */
-         errorptr,                     /* Where to put an error message */
-         (bravalue == OP_ASSERTBACK ||
-          bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
-         skipbytes,                    /* Skip over OP_COND/OP_BRANUMBER */
-         &subreqchar,                  /* For possible last char */
-         &subcountlits,                /* For literal count */
-         cd))                          /* Tables block */
-      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. */
-
-    else if (bravalue == OP_COND)
-      {
-      uschar *tc = code;
-      condcount = 0;
-
-      do {
-         condcount++;
-         tc += (tc[1] << 8) | tc[2];
-         }
-      while (*tc != OP_KET);
-
-      if (condcount > 2)
-        {
-        *errorptr = ERR27;
-        goto FAILED;
-        }
-      }
-
-    /* Handle updating of the required character. If the subpattern didn't
-    set one, leave it as it was. Otherwise, update it for normal brackets of
-    all kinds, forward assertions, and conditions with two branches. Don't
-    update the literal count for forward assertions, however. If the bracket
-    is followed by a quantifier with zero repeat, we have to back off. Hence
-    the definition of prevreqchar and subcountlits outside the main loop so
-    that they can be accessed for the back off. */
-
-    if (subreqchar > 0 &&
-         (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_ASSERT ||
-         (bravalue == OP_COND && condcount == 2)))
-      {
-      prevreqchar = *reqchar;
-      *reqchar = subreqchar;
-      if (bravalue != OP_ASSERT) *countlits += subcountlits;
-      }
-
-    /* Now update the main code pointer to the end of the group. */
-
-    code = tempcode;
-
-    /* Error if hit end of pattern */
-
-    if (*ptr != ')')
-      {
-      *errorptr = ERR14;
-      goto FAILED;
-      }
-    break;
-
-    /* Check \ for being a real metacharacter; if not, fall through and handle
-    it as a data character at the start of a string. Escape items are checked
-    for validity in the pre-compiling pass. */
-
-    case '\\':
-    tempptr = ptr;
-    c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
-
-    /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
-    are arranged to be the negation of the corresponding OP_values. 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. */
-
-    if (c < 0)
-      {
-      if (-c >= ESC_REF)
-        {
-        int number = -c - ESC_REF;
-        previous = code;
-        *code++ = OP_REF;
-        *code++ = number >> 8;
-        *code++ = number & 255;
-        }
-      else
-        {
-        previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
-        *code++ = -c;
-        }
-      continue;
-      }
-
-    /* Data character: reset and fall through */
-
-    ptr = tempptr;
-    c = '\\';
-
-    /* Handle a run of data characters until a metacharacter is encountered.
-    The first character is guaranteed not to be whitespace or # when the
-    extended flag is set. */
-
-    NORMAL_CHAR:
-    default:
-    previous = code;
-    *code = OP_CHARS;
-    code += 2;
-    length = 0;
-
-    do
-      {
-      if ((options & PCRE_EXTENDED) != 0)
-        {
-        if ((cd->ctypes[c] & ctype_space) != 0) continue;
-        if (c == '#')
-          {
-          /* The space before the ; is to avoid a warning on a silly compiler
-          on the Macintosh. */
-          while ((c = *(++ptr)) != 0 && c != '\n') ;
-          if (c == 0) break;
-          continue;
-          }
-        }
-
-      /* Backslash may introduce a data char or a metacharacter. Escaped items
-      are checked for validity in the pre-compiling pass. Stop the string
-      before a metaitem. */
-
-      if (c == '\\')
-        {
-        tempptr = ptr;
-        c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
-        if (c < 0) { ptr = tempptr; break; }
-
-        /* If a character is > 127 in UTF-8 mode, we have to turn it into
-        two or more characters in the UTF-8 encoding. */
+                                                        if (d < 0) {
+                                                                if (d == -ESC_b)
+                                                                        d = '\b';
+                                                                else {
+                                                                        ptr = oldptr - 2;
+                                                                        goto SINGLE_CHARACTER;
+                                                                }
+                                                        }
+                                                }
+
+                                                if (d < c) {
+                                                        *errorptr = ERR8;
+                                                        goto FAILED;
+                                                }
+
+                                                for (; c <= d; c++) {
+                                                        class[c / 8] |= (1 << (c & 7));
+                                                        if ((options & PCRE_CASELESS) != 0) {
+                                                                int uc = cd->fcc[c];
+                                                                class[uc / 8] |= (1 << (uc & 7));
+                                                        }
+                                                        class_charcount++;
+                                                        class_lastchar = c;
+                                                }
+                                                continue;
+                                        }
+
+                                  SINGLE_CHARACTER:
+
+                                        class[c / 8] |= (1 << (c & 7));
+                                        if ((options & PCRE_CASELESS) != 0) {
+                                                c = cd->fcc[c];
+                                                class[c / 8] |= (1 << (c & 7));
+                                        }
+                                        class_charcount++;
+                                        class_lastchar = c;
+                                }
+
+                                while ((c = *(++ptr)) != ']');
+
+                                if (class_charcount == 1 && class_lastchar >= 0) {
+                                        if (negate_class) {
+                                                code[-1] = OP_NOT;
+                                        }
+                                        else {
+                                                code[-1] = OP_CHARS;
+                                                *code++ = 1;
+                                        }
+                                        *code++ = class_lastchar;
+                                }
+
+                                else {
+                                        if (negate_class)
+                                                for (c = 0; c < 32; c++)
+                                                        code[c] = ~class[c];
+                                        else
+                                                memcpy(code, class, 32);
+                                        code += 32;
+                                }
+                                break;
+
+                        case '{':
+                                if (!is_counted_repeat(ptr + 1, cd))
+                                        goto NORMAL_CHAR;
+                                ptr =
+                                        read_repeat_counts(ptr + 1, &repeat_min, &repeat_max,
+                                                                           errorptr, cd);
+                                if (*errorptr != NULL)
+                                        goto FAILED;
+                                goto REPEAT;
+
+                        case '*':
+                                repeat_min = 0;
+                                repeat_max = -1;
+                                goto REPEAT;
+
+                        case '+':
+                                repeat_min = 1;
+                                repeat_max = -1;
+                                goto REPEAT;
+
+                        case '?':
+                                repeat_min = 0;
+                                repeat_max = 1;
+
+                          REPEAT:
+                                if (previous == NULL) {
+                                        *errorptr = ERR9;
+                                        goto FAILED;
+                                }
+
+                                if (ptr[1] == '?') {
+                                        repeat_type = greedy_non_default;
+                                        ptr++;
+                                }
+                                else
+                                        repeat_type = greedy_default;
+
+                                if (*previous == OP_CHARS) {
+                                        int len = previous[1];
+
+                                        if (repeat_min == 0)
+                                                *reqchar = prevreqchar;
+                                        *countlits += repeat_min - 1;
+
+                                        if (len == 1) {
+                                                c = previous[2];
+                                                code = previous;
+                                        }
+                                        else {
+                                                c = previous[len + 1];
+                                                previous[1]--;
+                                                code--;
+                                        }
+                                        op_type = 0;
+                                        goto OUTPUT_SINGLE_REPEAT;
+                                }
+
+                                else if ((int)*previous == OP_NOT) {
+                                        op_type = OP_NOTSTAR - OP_STAR;
+                                        c = previous[1];
+                                        code = previous;
+                                        goto OUTPUT_SINGLE_REPEAT;
+                                }
+
+                                else if ((int)*previous < OP_EODN || *previous == OP_ANY) {
+                                        op_type = OP_TYPESTAR - OP_STAR;
+                                        c = *previous;
+                                        code = previous;
+
+                                  OUTPUT_SINGLE_REPEAT:
+
+                                        if (repeat_max == 0)
+                                                goto END_REPEAT;
+
+                                        repeat_type += op_type;
+
+                                        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;
+                                                        *code++ = repeat_max >> 8;
+                                                        *code++ = (repeat_max & 255);
+                                                }
+                                        }
+
+                                        else if (repeat_min == 1 && repeat_max == -1)
+                                                *code++ = OP_PLUS + repeat_type;
+
+                                        else {
+                                                if (repeat_min != 1) {
+                                                        *code++ = OP_EXACT + op_type;
+                                                        *code++ = repeat_min >> 8;
+                                                        *code++ = (repeat_min & 255);
+                                                }
+
+                                                else if (*previous == OP_CHARS) {
+                                                        if (code == previous)
+                                                                code += 2;
+                                                        else
+                                                                previous[1]++;
+                                                }
+
+                                                else if (*previous == OP_NOT)
+                                                        code++;
+
+                                                if (repeat_max < 0) {
+                                                        *code++ = c;
+                                                        *code++ = OP_STAR + repeat_type;
+                                                }
+
+                                                else if (repeat_max != repeat_min) {
+                                                        *code++ = c;
+                                                        repeat_max -= repeat_min;
+                                                        *code++ = OP_UPTO + repeat_type;
+                                                        *code++ = repeat_max >> 8;
+                                                        *code++ = (repeat_max & 255);
+                                                }
+                                        }
+
+                                        *code++ = c;
+                                }
+
+                                else if (*previous == OP_CLASS || *previous == OP_REF) {
+                                        if (repeat_max == 0) {
+                                                code = previous;
+                                                goto END_REPEAT;
+                                        }
+                                        if (repeat_min == 0 && repeat_max == -1)
+                                                *code++ = OP_CRSTAR + repeat_type;
+                                        else if (repeat_min == 1 && repeat_max == -1)
+                                                *code++ = OP_CRPLUS + repeat_type;
+                                        else if (repeat_min == 0 && repeat_max == 1)
+                                                *code++ = OP_CRQUERY + repeat_type;
+                                        else {
+                                                *code++ = OP_CRRANGE + repeat_type;
+                                                *code++ = repeat_min >> 8;
+                                                *code++ = repeat_min & 255;
+                                                if (repeat_max == -1)
+                                                        repeat_max = 0;
+                                                *code++ = repeat_max >> 8;
+                                                *code++ = repeat_max & 255;
+                                        }
+                                }
+
+                                else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE
+                                                 || (int)*previous == OP_COND) {
+                                        register int i;
+                                        int ketoffset = 0;
+                                        int len = code - previous;
+                                        uschar *bralink = NULL;
+
+                                        if (repeat_max == -1) {
+                                                register uschar *ket = previous;
+                                                do
+                                                        ket += (ket[1] << 8) + ket[2];
+                                                while (*ket != OP_KET);
+                                                ketoffset = code - ket;
+                                        }
+
+                                        if (repeat_min == 0) {
+                                                if (subcountlits > 0) {
+                                                        *reqchar = prevreqchar;
+                                                        *countlits -= subcountlits;
+                                                }
+
+                                                if (repeat_max == 0) {
+                                                        code = previous;
+                                                        goto END_REPEAT;
+                                                }
+
+                                                if (repeat_max <= 1) {
+                                                        memmove(previous + 1, previous, len);
+                                                        code++;
+                                                        *previous++ = OP_BRAZERO + repeat_type;
+                                                }
+
+                                                else {
+                                                        int offset;
+                                                        memmove(previous + 4, previous, len);
+                                                        code += 4;
+                                                        *previous++ = OP_BRAZERO + repeat_type;
+                                                        *previous++ = OP_BRA;
+
+                                                        offset =
+                                                                (bralink == NULL) ? 0 : previous - bralink;
+                                                        bralink = previous;
+                                                        *previous++ = offset >> 8;
+                                                        *previous++ = offset & 255;
+                                                }
+
+                                                repeat_max--;
+                                        }
+
+                                        else {
+                                                for (i = 1; i < repeat_min; i++) {
+                                                        memcpy(code, previous, len);
+                                                        code += len;
+                                                }
+                                                if (repeat_max > 0)
+                                                        repeat_max -= repeat_min;
+                                        }
+
+                                        if (repeat_max >= 0) {
+                                                for (i = repeat_max - 1; i >= 0; i--) {
+                                                        *code++ = OP_BRAZERO + repeat_type;
+
+                                                        if (i != 0) {
+                                                                int offset;
+                                                                *code++ = OP_BRA;
+                                                                offset =
+                                                                        (bralink == NULL) ? 0 : code - bralink;
+                                                                bralink = code;
+                                                                *code++ = offset >> 8;
+                                                                *code++ = offset & 255;
+                                                        }
+
+                                                        memcpy(code, previous, len);
+                                                        code += len;
+                                                }
+
+                                                while (bralink != NULL) {
+                                                        int oldlinkoffset;
+                                                        int offset = code - bralink + 1;
+                                                        uschar *bra = code - offset;
+                                                        oldlinkoffset = (bra[1] << 8) + bra[2];
+                                                        bralink =
+                                                                (oldlinkoffset ==
+                                                                 0) ? NULL : bralink - oldlinkoffset;
+                                                        *code++ = OP_KET;
+                                                        *code++ = bra[1] = offset >> 8;
+                                                        *code++ = bra[2] = (offset & 255);
+                                                }
+                                        }
+
+                                        else
+                                                code[-ketoffset] = OP_KETRMAX + repeat_type;
+                                }
+
+                                else {
+                                        *errorptr = ERR11;
+                                        goto FAILED;
+                                }
+
+                          END_REPEAT:
+                                previous = NULL;
+                                break;
+
+                        case '(':
+                                newoptions = options;
+                                skipbytes = 0;
+
+                                if (*(++ptr) == '?') {
+                                        int set, unset;
+                                        int *optset;
+
+                                        switch (*(++ptr)) {
+                                                case '#':
+                                                        ptr++;
+                                                        while (*ptr != ')')
+                                                                ptr++;
+                                                        continue;
+
+                                                case ':':
+                                                        bravalue = OP_BRA;
+                                                        ptr++;
+                                                        break;
+
+                                                case '(':
+                                                        bravalue = OP_COND;
+                                                        if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0) {
+                                                                int condref = *ptr - '0';
+                                                                while (*(++ptr) != ')')
+                                                                        condref = condref * 10 + *ptr - '0';
+                                                                if (condref == 0) {
+                                                                        *errorptr = ERR35;
+                                                                        goto FAILED;
+                                                                }
+                                                                ptr++;
+                                                                code[3] = OP_CREF;
+                                                                code[4] = condref >> 8;
+                                                                code[5] = condref & 255;
+                                                                skipbytes = 3;
+                                                        }
+                                                        else
+                                                                ptr--;
+                                                        break;
+
+                                                case '=':
+                                                        bravalue = OP_ASSERT;
+                                                        ptr++;
+                                                        break;
+
+                                                case '!':
+                                                        bravalue = OP_ASSERT_NOT;
+                                                        ptr++;
+                                                        break;
+
+                                                case '<':
+                                                        switch (*(++ptr)) {
+                                                                case '=':
+                                                                        bravalue = OP_ASSERTBACK;
+                                                                        ptr++;
+                                                                        break;
+
+                                                                case '!':
+                                                                        bravalue = OP_ASSERTBACK_NOT;
+                                                                        ptr++;
+                                                                        break;
+
+                                                                default:
+                                                                        *errorptr = ERR24;
+                                                                        goto FAILED;
+                                                        }
+                                                        break;
+
+                                                case '>':
+                                                        bravalue = OP_ONCE;
+                                                        ptr++;
+                                                        break;
+
+                                                case 'R':
+                                                        *code++ = OP_RECURSE;
+                                                        ptr++;
+                                                        continue;
+
+                                                default:
+                                                        set = unset = 0;
+                                                        optset = &set;
+
+                                                        while (*ptr != ')' && *ptr != ':') {
+                                                                switch (*ptr++) {
+                                                                        case '-':
+                                                                                optset = &unset;
+                                                                                break;
+
+                                                                        case 'i':
+                                                                                *optset |= PCRE_CASELESS;
+                                                                                break;
+                                                                        case 'm':
+                                                                                *optset |= PCRE_MULTILINE;
+                                                                                break;
+                                                                        case 's':
+                                                                                *optset |= PCRE_DOTALL;
+                                                                                break;
+                                                                        case 'x':
+                                                                                *optset |= PCRE_EXTENDED;
+                                                                                break;
+                                                                        case 'U':
+                                                                                *optset |= PCRE_UNGREEDY;
+                                                                                break;
+                                                                        case 'X':
+                                                                                *optset |= PCRE_EXTRA;
+                                                                                break;
+
+                                                                        default:
+                                                                                *errorptr = ERR12;
+                                                                                goto FAILED;
+                                                                }
+                                                        }
+
+                                                        newoptions = (options | set) & (~unset);
+
+                                                        if (*ptr == ')') {
+                                                                if ((options & PCRE_INGROUP) != 0 &&
+                                                                        (options & PCRE_IMS) !=
+                                                                        (newoptions & PCRE_IMS)) {
+                                                                        *code++ = OP_OPT;
+                                                                        *code++ = *optchanged =
+                                                                                newoptions & PCRE_IMS;
+                                                                }
+                                                                options = newoptions;
+                                                                previous = NULL;
+                                                                continue;
+                                                        }
+
+                                                        bravalue = OP_BRA;
+                                                        ptr++;
+                                        }
+                                }
+
+                                else {
+                                        if (++(*brackets) > EXTRACT_BASIC_MAX) {
+                                                bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
+                                                code[3] = OP_BRANUMBER;
+                                                code[4] = *brackets >> 8;
+                                                code[5] = *brackets & 255;
+                                                skipbytes = 3;
+                                        }
+                                        else
+                                                bravalue = OP_BRA + *brackets;
+                                }
+
+                                previous = (bravalue >= OP_ONCE) ? code : NULL;
+                                *code = bravalue;
+                                tempcode = code;
+
+                                if (!compile_regex(options | PCRE_INGROUP,
+                                                                   ((options & PCRE_IMS) !=
+                                                                        (newoptions & PCRE_IMS)) ? newoptions &
+                                                                   PCRE_IMS : -1, brackets, &tempcode, &ptr,
+                                                                   errorptr, (bravalue == OP_ASSERTBACK
+                                                                                          || bravalue ==
+                                                                                          OP_ASSERTBACK_NOT), skipbytes,
+                                                                   &subreqchar, &subcountlits,
+                                                                   cd)) goto FAILED;
+
+                                else if (bravalue == OP_COND) {
+                                        uschar *tc = code;
+                                        condcount = 0;
+
+                                        do {
+                                                condcount++;
+                                                tc += (tc[1] << 8) | tc[2];
+                                        }
+                                        while (*tc != OP_KET);
+
+                                        if (condcount > 2) {
+                                                *errorptr = ERR27;
+                                                goto FAILED;
+                                        }
+                                }
+
+                                if (subreqchar > 0 &&
+                                        (bravalue >= OP_BRA || bravalue == OP_ONCE
+                                         || bravalue == OP_ASSERT || (bravalue == OP_COND
+                                                                                                  && condcount == 2))) {
+                                        prevreqchar = *reqchar;
+                                        *reqchar = subreqchar;
+                                        if (bravalue != OP_ASSERT)
+                                                *countlits += subcountlits;
+                                }
+
+                                code = tempcode;
+
+                                if (*ptr != ')') {
+                                        *errorptr = ERR14;
+                                        goto FAILED;
+                                }
+                                break;
+
+                        case '\\':
+                                tempptr = ptr;
+                                c =
+                                        check_escape(&ptr, errorptr, *brackets, options, FALSE,
+                                                                 cd);
+
+                                if (c < 0) {
+                                        if (-c >= ESC_REF) {
+                                                int number = -c - ESC_REF;
+                                                previous = code;
+                                                *code++ = OP_REF;
+                                                *code++ = number >> 8;
+                                                *code++ = number & 255;
+                                        }
+                                        else {
+                                                previous = (-c > ESC_b && -c < ESC_Z) ? code : NULL;
+                                                *code++ = -c;
+                                        }
+                                        continue;
+                                }
+
+                                ptr = tempptr;
+                                c = '\\';
+
+                          NORMAL_CHAR:
+                        default:
+                                previous = code;
+                                *code = OP_CHARS;
+                                code += 2;
+                                length = 0;
+
+                                do {
+                                        if ((options & PCRE_EXTENDED) != 0) {
+                                                if ((cd->ctypes[c] & ctype_space) != 0)
+                                                        continue;
+                                                if (c == '#') {
+                                                        while ((c = *(++ptr)) != 0 && c != '\n') ;
+                                                        if (c == 0)
+                                                                break;
+                                                        continue;
+                                                }
+                                        }
+
+                                        if (c == '\\') {
+                                                tempptr = ptr;
+                                                c =
+                                                        check_escape(&ptr, errorptr, *brackets, options,
+                                                                                 FALSE, cd);
+                                                if (c < 0) {
+                                                        ptr = tempptr;
+                                                        break;
+                                                }
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-        if (c > 127 && (options & PCRE_UTF8) != 0)
-          {
-          uschar buffer[8];
-          int len = ord2utf8(c, buffer);
-          for (c = 0; c < len; c++) *code++ = buffer[c];
-          length += len;
-          continue;
-          }
+                                                if (c > 127 && (options & PCRE_UTF8) != 0) {
+                                                        uschar buffer[8];
+                                                        int len = ord2utf8(c, buffer);
+                                                        for (c = 0; c < len; c++)
+                                                                *code++ = buffer[c];
+                                                        length += len;
+                                                        continue;
+                                                }
 #endif
-        }
-
-      /* Ordinary character or single-char escape */
-
-      *code++ = c;
-      length++;
-      }
-
-    /* This "while" is the end of the "do" above. */
-
-    while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
+                                        }
 
-    /* Update the last character and the count of literals */
-
-    prevreqchar = (length > 1)? code[-2] : *reqchar;
-    *reqchar = code[-1];
-    *countlits += length;
-
-    /* Compute the length and set it in the data vector, and advance to
-    the next state. */
-
-    previous[1] = length;
-    if (length < MAXLIT) ptr--;
-    break;
-    }
-  }                   /* 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;
+                                        *code++ = c;
+                                        length++;
+                                }
+
+                                while (length < MAXLIT
+                                           && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
+
+                                prevreqchar = (length > 1) ? code[-2] : *reqchar;
+                                *reqchar = code[-1];
+                                *countlits += length;
+
+                                previous[1] = length;
+                                if (length < MAXLIT)
+                                        ptr--;
+                                break;
+                }
+        }
+
+  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.
-
-Argument:
-  options     the option bits
-  optchanged  new ims options to set as if (?ims) were at the start, or -1
-               for no change
-  brackets    -> int containing the number of extracting brackets used
-  codeptr     -> the address of the current code pointer
-  ptrptr      -> the address of the current pattern pointer
-  errorptr    -> pointer to error message
-  lookbehind  TRUE if this is a lookbehind assertion
-  skipbytes   skip this many bytes at start (for OP_COND, OP_BRANUMBER)
-  reqchar     -> place to put the last required character, or a negative number
-  countlits   -> place to put the shortest literal count of any branch
-  cd          points to the data block with tables pointers
-
-Returns:      TRUE on success
-*/
-
 static BOOL
-compile_regex(int options, int optchanged, int *brackets, uschar **codeptr,
-  const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int skipbytes,
-  int *reqchar, int *countlits, compile_data *cd)
+compile_regex(int options, int optchanged, int *brackets, uschar ** codeptr,
+                          const uschar ** ptrptr, const char **errorptr, BOOL lookbehind,
+                          int skipbytes, int *reqchar, int *countlits, compile_data * cd)
 {
-const uschar *ptr = *ptrptr;
-uschar *code = *codeptr;
-uschar *last_branch = code;
-uschar *start_bracket = code;
-uschar *reverse_count = NULL;
-int oldoptions = options & PCRE_IMS;
-int branchreqchar, branchcountlits;
-
-*reqchar = -1;
-*countlits = INT_MAX;
-code += 3 + skipbytes;
-
-/* Loop for each alternative branch */
-
-for (;;)
-  {
-  int length;
-
-  /* Handle change of options */
-
-  if (optchanged >= 0)
-    {
-    *code++ = OP_OPT;
-    *code++ = optchanged;
-    options = (options & ~PCRE_IMS) | optchanged;
-    }
-
-  /* Set up dummy OP_REVERSE if lookbehind assertion */
-
-  if (lookbehind)
-    {
-    *code++ = OP_REVERSE;
-    reverse_count = code;
-    *code++ = 0;
-    *code++ = 0;
-    }
-
-  /* Now compile the branch */
-
-  if (!compile_branch(options, brackets, &code, &ptr, errorptr, &optchanged,
-      &branchreqchar, &branchcountlits, cd))
-    {
-    *ptrptr = ptr;
-    return FALSE;
-    }
-
-  /* Fill in the length of the last branch */
-
-  length = code - last_branch;
-  last_branch[1] = length >> 8;
-  last_branch[2] = length & 255;
-
-  /* Save the last required character if all branches have the same; a current
-  value of -1 means unset, while -2 means "previous branch had no last required
-  char".  */
-
-  if (*reqchar != -2)
-    {
-    if (branchreqchar >= 0)
-      {
-      if (*reqchar == -1) *reqchar = branchreqchar;
-      else if (*reqchar != branchreqchar) *reqchar = -2;
-      }
-    else *reqchar = -2;
-    }
-
-  /* Keep the shortest literal count */
-
-  if (branchcountlits < *countlits) *countlits = branchcountlits;
-
-  /* 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 (lookbehind)
-    {
-    *code = OP_END;
-    length = find_fixedlength(last_branch, options);
-
-    if (length < 0)
-      {
-      *errorptr = ERR25;
-      *ptrptr = ptr;
-      return FALSE;
-      }
-    reverse_count[0] = (length >> 8);
-    reverse_count[1] = length & 255;
-    }
-
-  /* Reached end of expression, either ')' or end of pattern. Insert a
-  terminating ket and the length of the whole bracketed item, and return,
-  leaving the pointer at the terminating char. If any of the ims options
-  were changed inside the group, compile a resetting op-code following. */
-
-  if (*ptr != '|')
-    {
-    length = code - start_bracket;
-    *code++ = OP_KET;
-    *code++ = length >> 8;
-    *code++ = length & 255;
-    if (optchanged >= 0)
-      {
-      *code++ = OP_OPT;
-      *code++ = oldoptions;
-      }
-    *codeptr = code;
-    *ptrptr = ptr;
-    return TRUE;
-    }
-
-  /* Another branch follows; insert an "or" node and advance the pointer. */
-
-  *code = OP_ALT;
-  last_branch = code;
-  code += 3;
-  ptr++;
-  }
-/* Control never reaches here */
+        const uschar *ptr = *ptrptr;
+        uschar *code = *codeptr;
+        uschar *last_branch = code;
+        uschar *start_bracket = code;
+        uschar *reverse_count = NULL;
+        int oldoptions = options & PCRE_IMS;
+        int branchreqchar, branchcountlits;
+
+        *reqchar = -1;
+        *countlits = INT_MAX;
+        code += 3 + skipbytes;
+
+        for (;;) {
+                int length;
+
+                if (optchanged >= 0) {
+                        *code++ = OP_OPT;
+                        *code++ = optchanged;
+                        options = (options & ~PCRE_IMS) | optchanged;
+                }
+
+                if (lookbehind) {
+                        *code++ = OP_REVERSE;
+                        reverse_count = code;
+                        *code++ = 0;
+                        *code++ = 0;
+                }
+
+                if (!compile_branch
+                        (options, brackets, &code, &ptr, errorptr, &optchanged,
+                         &branchreqchar, &branchcountlits, cd)) {
+                        *ptrptr = ptr;
+                        return FALSE;
+                }
+
+                length = code - last_branch;
+                last_branch[1] = length >> 8;
+                last_branch[2] = length & 255;
+
+                if (*reqchar != -2) {
+                        if (branchreqchar >= 0) {
+                                if (*reqchar == -1)
+                                        *reqchar = branchreqchar;
+                                else if (*reqchar != branchreqchar)
+                                        *reqchar = -2;
+                        }
+                        else
+                                *reqchar = -2;
+                }
+
+                if (branchcountlits < *countlits)
+                        *countlits = branchcountlits;
+
+                if (lookbehind) {
+                        *code = OP_END;
+                        length = find_fixedlength(last_branch, options);
+
+                        if (length < 0) {
+                                *errorptr = ERR25;
+                                *ptrptr = ptr;
+                                return FALSE;
+                        }
+                        reverse_count[0] = (length >> 8);
+                        reverse_count[1] = length & 255;
+                }
+
+                if (*ptr != '|') {
+                        length = code - start_bracket;
+                        *code++ = OP_KET;
+                        *code++ = length >> 8;
+                        *code++ = length & 255;
+                        if (optchanged >= 0) {
+                                *code++ = OP_OPT;
+                                *code++ = oldoptions;
+                        }
+                        *codeptr = code;
+                        *ptrptr = ptr;
+                        return TRUE;
+                }
+
+                *code = OP_ALT;
+                last_branch = code;
+                code += 3;
+                ptr++;
+        }
 }
 
-/*************************************************
-*      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 one application, a change of caseless option is
-important.
-
-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
-  optstop    TRUE to return on option change, otherwise change the options
-               value and continue
-
-Returns:     pointer to the first significant opcode
-*/
-
-static const uschar*
-first_significant_code(const uschar *code, int *options, int optbit,
-  BOOL optstop)
+static const uschar *first_significant_code(const uschar * code, int *options,
+                                                                                        int optbit, BOOL optstop)
 {
-for (;;)
-  {
-  switch ((int)*code)
-    {
-    case OP_OPT:
-    if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
-      {
-      if (optstop) return code;
-      *options = (int)code[1];
-      }
-    code += 2;
-    break;
-
-    case OP_CREF:
-    case OP_BRANUMBER:
-    code += 3;
-    break;
-
-    case OP_WORD_BOUNDARY:
-    case OP_NOT_WORD_BOUNDARY:
-    code++;
-    break;
-
-    case OP_ASSERT_NOT:
-    case OP_ASSERTBACK:
-    case OP_ASSERTBACK_NOT:
-    do code += (code[1] << 8) + code[2]; while (*code == OP_ALT);
-    code += 3;
-    break;
-
-    default:
-    return code;
-    }
-  }
-/* Control never reaches here */
+        for (;;) {
+                switch ((int)*code) {
+                        case OP_OPT:
+                                if (optbit > 0
+                                        && ((int)code[1] & optbit) != (*options & optbit)) {
+                                        if (optstop)
+                                                return code;
+                                        *options = (int)code[1];
+                                }
+                                code += 2;
+                                break;
+
+                        case OP_CREF:
+                        case OP_BRANUMBER:
+                                code += 3;
+                                break;
+
+                        case OP_WORD_BOUNDARY:
+                        case OP_NOT_WORD_BOUNDARY:
+                                code++;
+                                break;
+
+                        case OP_ASSERT_NOT:
+                        case OP_ASSERTBACK:
+                        case OP_ASSERTBACK_NOT:
+                                do
+                                        code += (code[1] << 8) + code[2];
+                                while (*code == OP_ALT);
+                                code += 3;
+                                break;
+
+                        default:
+                                return code;
+                }
+        }
 }
 
-/*************************************************
-*          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.
-
-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 them again.
-
-Arguments:
-  code       points to start of expression (the bracket)
-  options    points to the options setting
-
-Returns:     TRUE or FALSE
-*/
-
-static BOOL
-is_anchored(register const uschar *code, int *options)
+static BOOL is_anchored(register const uschar * code, int *options)
 {
-do {
-   const uschar *scode = first_significant_code(code + 3, options,
-     PCRE_MULTILINE, FALSE);
-   register int op = *scode;
-   if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
-     { if (!is_anchored(scode, options)) return FALSE; }
-   else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) &&
-            (*options & PCRE_DOTALL) != 0)
-     { if (scode[1] != OP_ANY) return FALSE; }
-   else if (op != OP_SOD &&
-           ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
-     return FALSE;
-   code += (code[1] << 8) + code[2];
-   }
-while (*code == OP_ALT);
-return TRUE;
+        do {
+                const uschar *scode = first_significant_code(code + 3, options,
+                                                                                                         PCRE_MULTILINE, FALSE);
+                register int op = *scode;
+                if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) {
+                        if (!is_anchored(scode, options))
+                                return FALSE;
+                }
+                else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) &&
+                                 (*options & PCRE_DOTALL) != 0) {
+                        if (scode[1] != OP_ANY)
+                                return FALSE;
+                }
+                else if (op != OP_SOD &&
+                                 ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
+                                return FALSE;
+                code += (code[1] << 8) + code[2];
+        }
+        while (*code == OP_ALT);
+        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).
-
-Argument:  points to start of expression (the bracket)
-Returns:   TRUE or FALSE
-*/
-
-static BOOL
-is_startline(const uschar *code)
+static BOOL is_startline(const uschar * code)
 {
-do {
-   const uschar *scode = first_significant_code(code + 3, NULL, 0, FALSE);
-   register int op = *scode;
-   if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
-     { if (!is_startline(scode)) return FALSE; }
-   else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
-     { if (scode[1] != OP_ANY) return FALSE; }
-   else if (op != OP_CIRC) return FALSE;
-   code += (code[1] << 8) + code[2];
-   }
-while (*code == OP_ALT);
-return TRUE;
+        do {
+                const uschar *scode =
+                        first_significant_code(code + 3, NULL, 0, FALSE);
+                register int op = *scode;
+                if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) {
+                        if (!is_startline(scode))
+                                return FALSE;
+                }
+                else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) {
+                        if (scode[1] != OP_ANY)
+                                return FALSE;
+                }
+                else if (op != OP_CIRC)
+                        return FALSE;
+                code += (code[1] << 8) + code[2];
+        }
+        while (*code == OP_ALT);
+        return TRUE;
 }
 
-/*************************************************
-*          Check for fixed first char            *
-*************************************************/
-
-/* Try to find out if there is a fixed first character. This is called for
-unanchored expressions, as it speeds up their processing quite considerably.
-Consider each alternative branch. If they all start with the same char, or with
-a bracket all of whose alternatives start with the same 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)
-
-Returns:     -1 or the fixed first char
-*/
-
-static int
-find_firstchar(const uschar *code, int *options)
+static int find_firstchar(const uschar * code, int *options)
 {
-register int c = -1;
-do {
-   int d;
-   const uschar *scode = first_significant_code(code + 3, options,
-     PCRE_CASELESS, TRUE);
-   register int op = *scode;
-
-   if (op >= OP_BRA) op = OP_BRA;
-
-   switch(op)
-     {
-     default:
-     return -1;
-
-     case OP_BRA:
-     case OP_ASSERT:
-     case OP_ONCE:
-     case OP_COND:
-     if ((d = find_firstchar(scode, options)) < 0) return -1;
-     if (c < 0) c = d; else if (c != d) return -1;
-     break;
-
-     case OP_EXACT:       /* Fall through */
-     scode++;
-
-     case OP_CHARS:       /* Fall through */
-     scode++;
-
-     case OP_PLUS:
-     case OP_MINPLUS:
-     if (c < 0) c = scode[1]; else if (c != scode[1]) return -1;
-     break;
-     }
-
-   code += (code[1] << 8) + code[2];
-   }
-while (*code == OP_ALT);
-return c;
+        register int c = -1;
+        do {
+                int d;
+                const uschar *scode = first_significant_code(code + 3, options,
+                                                                                                         PCRE_CASELESS, TRUE);
+                register int op = *scode;
+
+                if (op >= OP_BRA)
+                        op = OP_BRA;
+
+                switch (op) {
+                        default:
+                                return -1;
+
+                        case OP_BRA:
+                        case OP_ASSERT:
+                        case OP_ONCE:
+                        case OP_COND:
+                                if ((d = find_firstchar(scode, options)) < 0)
+                                        return -1;
+                                if (c < 0)
+                                        c = d;
+                                else if (c != d)
+                                        return -1;
+                                break;
+
+                        case OP_EXACT:
+                                scode++;
+
+                        case OP_CHARS:
+                                scode++;
+
+                        case OP_PLUS:
+                        case OP_MINPLUS:
+                                if (c < 0)
+                                        c = scode[1];
+                                else if (c != scode[1])
+                                        return -1;
+                                break;
+                }
+
+                code += (code[1] << 8) + code[2];
+        }
+        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.
-
-Arguments:
-  pattern      the regular expression
-  options      various option bits
-  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 *
-pcre_compile(const char *pattern, int options, const char **errorptr,
-  int *erroroffset, const unsigned char *tables)
+pcre *pcre_compile(const char *pattern, int options, const char **errorptr,
+                                   int *erroroffset, const unsigned char *tables)
 {
-real_pcre *re;
-int length = 3;      /* For initial BRA plus length */
-int runlength;
-int c, reqchar, countlits;
-int bracount = 0;
-int top_backref = 0;
-int branch_extra = 0;
-int branch_newextra;
-unsigned int brastackptr = 0;
-size_t size;
-uschar *code;
-const uschar *ptr;
-compile_data compile_block;
-int brastack[BRASTACK_SIZE];
-uschar bralenstack[BRASTACK_SIZE];
-
-/* Can't support UTF8 unless PCRE has been compiled to include the code. */
+        real_pcre *re;
+        int length = 3;
+        int runlength;
+        int c, reqchar, countlits;
+        int bracount = 0;
+        int top_backref = 0;
+        int branch_extra = 0;
+        int branch_newextra;
+        unsigned int brastackptr = 0;
+        size_t size;
+        uschar *code;
+        const uschar *ptr;
+        compile_data compile_block;
+        int brastack[BRASTACK_SIZE];
+        uschar bralenstack[BRASTACK_SIZE];
 
 #ifndef L2_UT_PCRE_SUPPORT_UTF8
-if ((options & PCRE_UTF8) != 0)
-  {
-  *errorptr = ERR32;
-  return NULL;
-  }
+        if ((options & PCRE_UTF8) != 0) {
+                *errorptr = ERR32;
+                return NULL;
+        }
 #endif
 
-/* We can't pass back an error message if errorptr is NULL; I guess the best we
-can do is just return NULL. */
-
-if (errorptr == NULL) return NULL;
-*errorptr = NULL;
-
-/* However, we can give a message for this error */
-
-if (erroroffset == NULL)
-  {
-  *errorptr = ERR16;
-  return NULL;
-  }
-*erroroffset = 0;
-
-if ((options & ~PUBLIC_OPTIONS) != 0)
-  {
-  *errorptr = ERR17;
-  return NULL;
-  }
-
-/* Set up pointers to the individual character tables */
-
-if (tables == NULL) tables = pcre_default_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;
-
-/* Reflect pattern for debugging output */
-
-/* The first thing to do is to make a pass over the pattern to compute the
-amount of store required to hold the compiled code. This does not have to be
-perfect as long as errors are overestimates. At the same time we can detect any
-internal flag settings. Make an attempt to correct for any counted white space
-if an "extended" flag setting appears late in the pattern. We can't be so
-clever for #-comments. */
-
-ptr = (const uschar *)(pattern - 1);
-while ((c = *(++ptr)) != 0)
-  {
-  int min, max;
-  int class_charcount;
-  int bracket_length;
-
-  if ((options & PCRE_EXTENDED) != 0)
-    {
-    if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
-    if (c == '#')
-      {
-      /* The space before the ; is to avoid a warning on a silly compiler
-      on the Macintosh. */
-      while ((c = *(++ptr)) != 0 && c != '\n') ;
-      continue;
-      }
-    }
-
-  switch(c)
-    {
-    /* A backslashed item may be an escaped "normal" character or a
-    character type. For a "normal" character, put the pointers and
-    character back so that tests for whitespace etc. in the input
-    are done correctly. */
-
-    case '\\':
-      {
-      const uschar *save_ptr = ptr;
-      c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block);
-      if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-      if (c >= 0)
-        {
-        ptr = save_ptr;
-        c = '\\';
-        goto NORMAL_CHAR;
-        }
-      }
-    length++;
-
-    /* A back reference needs an additional 2 bytes, plus either one or 5
-    bytes for a repeat. We also need to keep the value of the highest
-    back reference. */
-
-    if (c <= -ESC_REF)
-      {
-      int refnum = -c - ESC_REF;
-      if (refnum > top_backref) top_backref = refnum;
-      length += 2;   /* For single back reference */
-      if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
-        {
-        ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
-        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-        if ((min == 0 && (max == 1 || max == -1)) ||
-          (min == 1 && max == -1))
-            length++;
-        else length += 5;
-        if (ptr[1] == '?') ptr++;
-        }
-      }
-    continue;
-
-    case '^':
-    case '.':
-    case '$':
-    case '*':     /* These repeats won't be after brackets; */
-    case '+':     /* those are handled separately */
-    case '?':
-    length++;
-    continue;
-
-    /* This covers the cases of repeats after a single char, metachar, class,
-    or back reference. */
-
-    case '{':
-    if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR;
-    ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block);
-    if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-    if ((min == 0 && (max == 1 || max == -1)) ||
-      (min == 1 && max == -1))
-        length++;
-    else
-      {
-      length--;   /* Uncount the original char or metachar */
-      if (min == 1) length++; else if (min > 0) length += 4;
-      if (max > 0) length += 4; else length += 2;
-      }
-    if (ptr[1] == '?') ptr++;
-    continue;
-
-    /* An alternation contains an offset to the next branch or ket. If any ims
-    options changed in the previous branch(es), and/or if we are in a
-    lookbehind assertion, extra space will be needed at the start of the
-    branch. This is handled by branch_extra. */
-
-    case '|':
-    length += 3 + branch_extra;
-    continue;
-
-    /* A character class uses 33 characters. Don't worry about character types
-    that aren't allowed in classes - they'll get picked up during the compile.
-    A character class that contains only one character uses 2 or 3 bytes,
-    depending on whether it is negated or not. Notice this where we can. */
-
-    case '[':
-    class_charcount = 0;
-    if (*(++ptr) == '^') ptr++;
-    do
-      {
-      if (*ptr == '\\')
-        {
-        int ch = check_escape(&ptr, errorptr, bracount, options, TRUE,
-          &compile_block);
-        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-        if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
-        }
-      else class_charcount++;
-      ptr++;
-      }
-    while (*ptr != 0 && *ptr != ']');
-
-    /* Repeats for negated single chars are handled by the general code */
-
-    if (class_charcount == 1) length += 3; else
-      {
-      length += 33;
-
-      /* A repeat needs either 1 or 5 bytes. */
-
-      if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
-        {
-        ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
-        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-        if ((min == 0 && (max == 1 || max == -1)) ||
-          (min == 1 && max == -1))
-            length++;
-        else length += 5;
-        if (ptr[1] == '?') ptr++;
-        }
-      }
-    continue;
-
-    /* Brackets may be genuine groups or special things */
-
-    case '(':
-    branch_newextra = 0;
-    bracket_length = 3;
-
-    /* Handle special forms of bracket, which all start (? */
-
-    if (ptr[1] == '?')
-      {
-      int set, unset;
-      int *optset;
-
-      switch (c = ptr[2])
-        {
-        /* Skip over comments entirely */
-        case '#':
-        ptr += 3;
-        while (*ptr != 0 && *ptr != ')') ptr++;
-        if (*ptr == 0)
-          {
-          *errorptr = ERR18;
-          goto PCRE_ERROR_RETURN;
-          }
-        continue;
-
-        /* Non-referencing groups and lookaheads just move the pointer on, and
-        then behave like a non-special bracket, except that they don't increment
-        the count of extracting brackets. Ditto for the "once only" bracket,
-        which is in Perl from version 5.005. */
-
-        case ':':
-        case '=':
-        case '!':
-        case '>':
-        ptr += 2;
-        break;
-
-        /* A recursive call to the regex is an extension, to provide the
-        facility which can be obtained by $(?p{perl-code}) in Perl 5.6. */
-
-        case 'R':
-        if (ptr[3] != ')')
-          {
-          *errorptr = ERR29;
-          goto PCRE_ERROR_RETURN;
-          }
-        ptr += 3;
-        length += 1;
-        break;
-
-        /* Lookbehinds are in Perl from version 5.005 */
-
-        case '<':
-        if (ptr[3] == '=' || ptr[3] == '!')
-          {
-          ptr += 3;
-          branch_newextra = 3;
-          length += 3;         /* For the first branch */
-          break;
-          }
-        *errorptr = ERR24;
-        goto PCRE_ERROR_RETURN;
-
-        /* Conditionals are in Perl from version 5.005. The bracket must either
-        be followed by a number (for bracket reference) or by an assertion
-        group. */
-
-        case '(':
-        if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0)
-          {
-          ptr += 4;
-          length += 3;
-          while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++;
-          if (*ptr != ')')
-            {
-            *errorptr = ERR26;
-            goto PCRE_ERROR_RETURN;
-            }
-          }
-        else   /* An assertion must follow */
-          {
-          ptr++;   /* Can treat like ':' as far as spacing is concerned */
-          if (ptr[2] != '?' ||
-             (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') )
-            {
-            ptr += 2;    /* To get right offset in message */
-            *errorptr = ERR28;
-            goto PCRE_ERROR_RETURN;
-            }
-          }
-        break;
-
-        /* Else loop checking valid options until ) is met. Anything else is an
-        error. If we are without any brackets, i.e. at top level, the settings
-        act as if specified in the options, so massage the options immediately.
-        This is for backward compatibility with Perl 5.004. */
-
-        default:
-        set = unset = 0;
-        optset = &set;
-        ptr += 2;
-
-        for (;; ptr++)
-          {
-          c = *ptr;
-          switch (c)
-            {
-            case 'i':
-            *optset |= PCRE_CASELESS;
-            continue;
-
-            case 'm':
-            *optset |= PCRE_MULTILINE;
-            continue;
-
-            case 's':
-            *optset |= PCRE_DOTALL;
-            continue;
-
-            case 'x':
-            *optset |= PCRE_EXTENDED;
-            continue;
-
-            case 'X':
-            *optset |= PCRE_EXTRA;
-            continue;
-
-            case 'U':
-            *optset |= PCRE_UNGREEDY;
-            continue;
-
-            case '-':
-            optset = &unset;
-            continue;
-
-            /* A termination by ')' indicates an options-setting-only item;
-            this is global at top level; otherwise nothing is done here and
-            it is handled during the compiling process on a per-bracket-group
-            basis. */
-
-            case ')':
-            if (brastackptr == 0)
-              {
-              options = (options | set) & (~unset);
-              set = unset = 0;     /* To save length */
-              }
-            /* Fall through */
-
-            /* A termination by ':' indicates the start of a nested group with
-            the given options set. This is again handled at compile time, but
-            we must allow for compiled space if any of the ims options are
-            set. We also have to allow for resetting space at the end of
-            the group, which is why 4 is added to the length and not just 2.
-            If there are several changes of options within the same group, this
-            will lead to an over-estimate on the length, but this shouldn't
-            matter very much. We also have to allow for resetting options at
-            the start of any alternations, which we do by setting
-            branch_newextra to 2. Finally, we record whether the case-dependent
-            flag ever changes within the regex. This is used by the "required
-            character" code. */
-
-            case ':':
-            if (((set|unset) & PCRE_IMS) != 0)
-              {
-              length += 4;
-              branch_newextra = 2;
-              if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED;
-              }
-            goto END_OPTIONS;
-
-            /* Unrecognized option character */
-
-            default:
-            *errorptr = ERR12;
-            goto PCRE_ERROR_RETURN;
-            }
-          }
-
-        /* If we hit a closing bracket, that's it - this is a freestanding
-        option-setting. We need to ensure that branch_extra is updated if
-        necessary. The only values branch_newextra can have here are 0 or 2.
-        If the value is 2, then branch_extra must either be 2 or 5, depending
-        on whether this is a lookbehind group or not. */
-
-        END_OPTIONS:
-        if (c == ')')
-          {
-          if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3))
-            branch_extra += branch_newextra;
-          continue;
-          }
-
-        /* If options were terminated by ':' control comes here. Fall through
-        to handle the group below. */
-        }
-      }
-
-    /* Extracting brackets must be counted so we can process escapes in a
-    Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to
-    need an additional 3 bytes of store per extracting bracket. */
-
-    else
-      {
-      bracount++;
-      if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3;
-      }
-
-    /* Save length for computing whole length at end if there's a repeat that
-    requires duplication of the group. Also save the current value of
-    branch_extra, and start the new group with the new value. If non-zero, this
-    will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */
-
-    if (brastackptr >= sizeof(brastack)/sizeof(int))
-      {
-      *errorptr = ERR19;
-      goto PCRE_ERROR_RETURN;
-      }
-
-    bralenstack[brastackptr] = branch_extra;
-    branch_extra = branch_newextra;
-
-    brastack[brastackptr++] = length;
-    length += bracket_length;
-    continue;
-
-    /* Handle ket. Look for subsequent max/min; for certain sets of values we
-    have to replicate this bracket up to that many times. If brastackptr is
-    0 this is an unmatched bracket which will generate an error, but take care
-    not to try to access brastack[-1] when computing the length and restoring
-    the branch_extra value. */
-
-    case ')':
-    length += 3;
-      {
-      int minval = 1;
-      int maxval = 1;
-      int duplength;
-
-      if (brastackptr > 0)
-        {
-        duplength = length - brastack[--brastackptr];
-        branch_extra = bralenstack[brastackptr];
-        }
-      else duplength = 0;
-
-      /* Leave ptr at the final char; for read_repeat_counts this happens
-      automatically; for the others we need an increment. */
-
-      if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block))
-        {
-        ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr,
-          &compile_block);
-        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-        }
-      else if (c == '*') { minval = 0; maxval = -1; ptr++; }
-      else if (c == '+') { maxval = -1; ptr++; }
-      else if (c == '?') { minval = 0; ptr++; }
-
-      /* If the minimum is zero, we have to allow for an OP_BRAZERO before the
-      group, and if the maximum is greater than zero, we have to replicate
-      maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting
-      bracket set - hence the 7. */
-
-      if (minval == 0)
-        {
-        length++;
-        if (maxval > 0) length += (maxval - 1) * (duplength + 7);
-        }
-
-      /* When the minimum is greater than zero, 1 we have to replicate up to
-      minval-1 times, with no additions required in the copies. Then, if
-      there is a limited maximum we have to replicate up to maxval-1 times
-      allowing for a BRAZERO item before each optional copy and nesting
-      brackets for all but one of the optional copies. */
-
-      else
-        {
-        length += (minval - 1) * duplength;
-        if (maxval > minval)   /* Need this test as maxval=-1 means no limit */
-          length += (maxval - minval) * (duplength + 7) - 6;
-        }
-      }
-    continue;
-
-    /* Non-special character. For a run of such characters the length required
-    is the number of characters + 2, except that the maximum run length is 255.
-    We won't get a skipped space or a non-data escape or the start of a #
-    comment as the first character, so the length can't be zero. */
-
-    NORMAL_CHAR:
-    default:
-    length += 2;
-    runlength = 0;
-    do
-      {
-      if ((options & PCRE_EXTENDED) != 0)
-        {
-        if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
-        if (c == '#')
-          {
-          /* The space before the ; is to avoid a warning on a silly compiler
-          on the Macintosh. */
-          while ((c = *(++ptr)) != 0 && c != '\n') ;
-          continue;
-          }
-        }
-
-      /* Backslash may introduce a data char or a metacharacter; stop the
-      string before the latter. */
-
-      if (c == '\\')
-        {
-        const uschar *saveptr = ptr;
-        c = check_escape(&ptr, errorptr, bracount, options, FALSE,
-          &compile_block);
-        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
-        if (c < 0) { ptr = saveptr; break; }
+        if (errorptr == NULL)
+                return NULL;
+        *errorptr = NULL;
+
+        if (erroroffset == NULL) {
+                *errorptr = ERR16;
+                return NULL;
+        }
+        *erroroffset = 0;
+
+        if ((options & ~PUBLIC_OPTIONS) != 0) {
+                *errorptr = ERR17;
+                return NULL;
+        }
+
+        if (tables == NULL)
+                tables = pcre_default_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;
+
+        ptr = (const uschar *)(pattern - 1);
+        while ((c = *(++ptr)) != 0) {
+                int min, max;
+                int class_charcount;
+                int bracket_length;
+
+                if ((options & PCRE_EXTENDED) != 0) {
+                        if ((compile_block.ctypes[c] & ctype_space) != 0)
+                                continue;
+                        if (c == '#') {
+                                while ((c = *(++ptr)) != 0 && c != '\n') ;
+                                continue;
+                        }
+                }
+
+                switch (c) {
+                        case '\\':
+                                {
+                                        const uschar *save_ptr = ptr;
+                                        c =
+                                                check_escape(&ptr, errorptr, bracount, options, FALSE,
+                                                                         &compile_block);
+                                        if (*errorptr != NULL)
+                                                goto PCRE_ERROR_RETURN;
+                                        if (c >= 0) {
+                                                ptr = save_ptr;
+                                                c = '\\';
+                                                goto NORMAL_CHAR;
+                                        }
+                                }
+                                length++;
+
+                                if (c <= -ESC_REF) {
+                                        int refnum = -c - ESC_REF;
+                                        if (refnum > top_backref)
+                                                top_backref = refnum;
+                                        length += 2;
+                                        if (ptr[1] == '{'
+                                                && is_counted_repeat(ptr + 2, &compile_block)) {
+                                                ptr =
+                                                        read_repeat_counts(ptr + 2, &min, &max, errorptr,
+                                                                                           &compile_block);
+                                                if (*errorptr != NULL)
+                                                        goto PCRE_ERROR_RETURN;
+                                                if ((min == 0 && (max == 1 || max == -1)) ||
+                                                        (min == 1 && max == -1))
+                                                        length++;
+                                                else
+                                                        length += 5;
+                                                if (ptr[1] == '?')
+                                                        ptr++;
+                                        }
+                                }
+                                continue;
+
+                        case '^':
+                        case '.':
+                        case '$':
+                        case '*':
+                        case '+':
+                        case '?':
+                                length++;
+                                continue;
+
+                        case '{':
+                                if (!is_counted_repeat(ptr + 1, &compile_block))
+                                        goto NORMAL_CHAR;
+                                ptr =
+                                        read_repeat_counts(ptr + 1, &min, &max, errorptr,
+                                                                           &compile_block);
+                                if (*errorptr != NULL)
+                                        goto PCRE_ERROR_RETURN;
+                                if ((min == 0 && (max == 1 || max == -1)) ||
+                                        (min == 1 && max == -1))
+                                        length++;
+                                else {
+                                        length--;
+                                        if (min == 1)
+                                                length++;
+                                        else if (min > 0)
+                                                length += 4;
+                                        if (max > 0)
+                                                length += 4;
+                                        else
+                                                length += 2;
+                                }
+                                if (ptr[1] == '?')
+                                        ptr++;
+                                continue;
+
+                        case '|':
+                                length += 3 + branch_extra;
+                                continue;
+
+                        case '[':
+                                class_charcount = 0;
+                                if (*(++ptr) == '^')
+                                        ptr++;
+                                do {
+                                        if (*ptr == '\\') {
+                                                int ch =
+                                                        check_escape(&ptr, errorptr, bracount, options,
+                                                                                 TRUE,
+                                                                                 &compile_block);
+                                                if (*errorptr != NULL)
+                                                        goto PCRE_ERROR_RETURN;
+                                                if (-ch == ESC_b)
+                                                        class_charcount++;
+                                                else
+                                                        class_charcount = 10;
+                                        }
+                                        else
+                                                class_charcount++;
+                                        ptr++;
+                                }
+                                while (*ptr != 0 && *ptr != ']');
+
+                                if (class_charcount == 1)
+                                        length += 3;
+                                else {
+                                        length += 33;
+
+                                        if (*ptr != 0 && ptr[1] == '{'
+                                                && is_counted_repeat(ptr + 2, &compile_block)) {
+                                                ptr =
+                                                        read_repeat_counts(ptr + 2, &min, &max, errorptr,
+                                                                                           &compile_block);
+                                                if (*errorptr != NULL)
+                                                        goto PCRE_ERROR_RETURN;
+                                                if ((min == 0 && (max == 1 || max == -1)) ||
+                                                        (min == 1 && max == -1))
+                                                        length++;
+                                                else
+                                                        length += 5;
+                                                if (ptr[1] == '?')
+                                                        ptr++;
+                                        }
+                                }
+                                continue;
+
+                        case '(':
+                                branch_newextra = 0;
+                                bracket_length = 3;
+
+                                if (ptr[1] == '?') {
+                                        int set, unset;
+                                        int *optset;
+
+                                        switch (c = ptr[2]) {
+                                                case '#':
+                                                        ptr += 3;
+                                                        while (*ptr != 0 && *ptr != ')')
+                                                                ptr++;
+                                                        if (*ptr == 0) {
+                                                                *errorptr = ERR18;
+                                                                goto PCRE_ERROR_RETURN;
+                                                        }
+                                                        continue;
+
+                                                case ':':
+                                                case '=':
+                                                case '!':
+                                                case '>':
+                                                        ptr += 2;
+                                                        break;
+
+                                                case 'R':
+                                                        if (ptr[3] != ')') {
+                                                                *errorptr = ERR29;
+                                                                goto PCRE_ERROR_RETURN;
+                                                        }
+                                                        ptr += 3;
+                                                        length += 1;
+                                                        break;
+
+                                                case '<':
+                                                        if (ptr[3] == '=' || ptr[3] == '!') {
+                                                                ptr += 3;
+                                                                branch_newextra = 3;
+                                                                length += 3;
+                                                                break;
+                                                        }
+                                                        *errorptr = ERR24;
+                                                        goto PCRE_ERROR_RETURN;
+
+                                                case '(':
+                                                        if ((compile_block.ctypes[ptr[3]] & ctype_digit)
+                                                                != 0) {
+                                                                ptr += 4;
+                                                                length += 3;
+                                                                while (
+                                                                           (compile_block.
+                                                                                ctypes[*ptr] & ctype_digit) != 0)
+                                                                        ptr++;
+                                                                if (*ptr != ')') {
+                                                                        *errorptr = ERR26;
+                                                                        goto PCRE_ERROR_RETURN;
+                                                                }
+                                                        }
+                                                        else {
+                                                                ptr++;
+                                                                if (ptr[2] != '?' ||
+                                                                        (ptr[3] != '=' && ptr[3] != '!'
+                                                                         && ptr[3] != '<')) {
+                                                                        ptr += 2;
+                                                                        *errorptr = ERR28;
+                                                                        goto PCRE_ERROR_RETURN;
+                                                                }
+                                                        }
+                                                        break;
+
+                                                default:
+                                                        set = unset = 0;
+                                                        optset = &set;
+                                                        ptr += 2;
+
+                                                        for (;; ptr++) {
+                                                                c = *ptr;
+                                                                switch (c) {
+                                                                        case 'i':
+                                                                                *optset |= PCRE_CASELESS;
+                                                                                continue;
+
+                                                                        case 'm':
+                                                                                *optset |= PCRE_MULTILINE;
+                                                                                continue;
+
+                                                                        case 's':
+                                                                                *optset |= PCRE_DOTALL;
+                                                                                continue;
+
+                                                                        case 'x':
+                                                                                *optset |= PCRE_EXTENDED;
+                                                                                continue;
+
+                                                                        case 'X':
+                                                                                *optset |= PCRE_EXTRA;
+                                                                                continue;
+
+                                                                        case 'U':
+                                                                                *optset |= PCRE_UNGREEDY;
+                                                                                continue;
+
+                                                                        case '-':
+                                                                                optset = &unset;
+                                                                                continue;
+
+                                                                        case ')':
+                                                                                if (brastackptr == 0) {
+                                                                                        options =
+                                                                                                (options | set) & (~unset);
+                                                                                        set = unset = 0;
+                                                                                }
+
+                                                                        case ':':
+                                                                                if (((set | unset) & PCRE_IMS) != 0) {
+                                                                                        length += 4;
+                                                                                        branch_newextra = 2;
+                                                                                        if (
+                                                                                                ((set | unset) &
+                                                                                                 PCRE_CASELESS) != 0)
+                                                                                                options |= PCRE_ICHANGED;
+                                                                                }
+                                                                                goto END_OPTIONS;
+
+                                                                        default:
+                                                                                *errorptr = ERR12;
+                                                                                goto PCRE_ERROR_RETURN;
+                                                                }
+                                                        }
+
+                                                  END_OPTIONS:
+                                                        if (c == ')') {
+                                                                if (branch_newextra == 2
+                                                                        && (branch_extra == 0
+                                                                                || branch_extra == 3)) branch_extra +=
+                                                                                branch_newextra;
+                                                                continue;
+                                                        }
+
+                                        }
+                                }
+
+                                else {
+                                        bracount++;
+                                        if (bracount > EXTRACT_BASIC_MAX)
+                                                bracket_length += 3;
+                                }
+
+                                if (brastackptr >= sizeof (brastack) / sizeof (int)) {
+                                        *errorptr = ERR19;
+                                        goto PCRE_ERROR_RETURN;
+                                }
+
+                                bralenstack[brastackptr] = branch_extra;
+                                branch_extra = branch_newextra;
+
+                                brastack[brastackptr++] = length;
+                                length += bracket_length;
+                                continue;
+
+                        case ')':
+                                length += 3;
+                                {
+                                        int minval = 1;
+                                        int maxval = 1;
+                                        int duplength;
+
+                                        if (brastackptr > 0) {
+                                                duplength = length - brastack[--brastackptr];
+                                                branch_extra = bralenstack[brastackptr];
+                                        }
+                                        else
+                                                duplength = 0;
+
+                                        if ((c = ptr[1]) == '{'
+                                                && is_counted_repeat(ptr + 2, &compile_block)) {
+                                                ptr =
+                                                        read_repeat_counts(ptr + 2, &minval, &maxval,
+                                                                                           errorptr, &compile_block);
+                                                if (*errorptr != NULL)
+                                                        goto PCRE_ERROR_RETURN;
+                                        }
+                                        else if (c == '*') {
+                                                minval = 0;
+                                                maxval = -1;
+                                                ptr++;
+                                        }
+                                        else if (c == '+') {
+                                                maxval = -1;
+                                                ptr++;
+                                        }
+                                        else if (c == '?') {
+                                                minval = 0;
+                                                ptr++;
+                                        }
+
+                                        if (minval == 0) {
+                                                length++;
+                                                if (maxval > 0)
+                                                        length += (maxval - 1) * (duplength + 7);
+                                        }
+
+                                        else {
+                                                length += (minval - 1) * duplength;
+                                                if (maxval > minval)
+                                                        length += (maxval - minval) * (duplength + 7) - 6;
+                                        }
+                                }
+                                continue;
+
+                          NORMAL_CHAR:
+                        default:
+                                length += 2;
+                                runlength = 0;
+                                do {
+                                        if ((options & PCRE_EXTENDED) != 0) {
+                                                if ((compile_block.ctypes[c] & ctype_space) != 0)
+                                                        continue;
+                                                if (c == '#') {
+                                                        while ((c = *(++ptr)) != 0 && c != '\n') ;
+                                                        continue;
+                                                }
+                                        }
+
+                                        if (c == '\\') {
+                                                const uschar *saveptr = ptr;
+                                                c =
+                                                        check_escape(&ptr, errorptr, bracount, options,
+                                                                                 FALSE, &compile_block);
+                                                if (*errorptr != NULL)
+                                                        goto PCRE_ERROR_RETURN;
+                                                if (c < 0) {
+                                                        ptr = saveptr;
+                                                        break;
+                                                }
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-        if (c > 127 && (options & PCRE_UTF8) != 0)
-          {
-          int i;
-          for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
-            if (c <= utf8_table1[i]) break;
-          runlength += i;
-          }
+                                                if (c > 127 && (options & PCRE_UTF8) != 0) {
+                                                        int i;
+                                                        for (i = 0;
+                                                                 i < sizeof (utf8_table1) / sizeof (int); i++)
+                                                                if (c <= utf8_table1[i])
+                                                                        break;
+                                                        runlength += i;
+                                                }
 #endif
-        }
-
-      /* Ordinary character or single-char escape */
+                                        }
 
-      runlength++;
-      }
-
-    /* This "while" is the end of the "do" above. */
-
-    while (runlength < MAXLIT &&
-      (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0);
-
-    ptr--;
-    length += runlength;
-    continue;
-    }
-  }
+                                        runlength++;
+                                }
 
-length += 4;    /* For final KET and END */
+                                while (runlength < MAXLIT &&
+                                           (compile_block.ctypes[c = *(++ptr)] & ctype_meta) ==
+                                           0);
+
+                                ptr--;
+                                length += runlength;
+                                continue;
+                }
+        }
+
+        length += 4;
+
+        if (length > 65539) {
+                *errorptr = ERR20;
+                return NULL;
+        }
+
+        size = length + offsetof(real_pcre, code[0]);
+        re = (real_pcre *) (pcre_malloc) (size);
+
+        if (re == NULL) {
+                *errorptr = ERR21;
+                return NULL;
+        }
+
+        re->magic_number = MAGIC_NUMBER;
+        re->size = size;
+        re->options = options;
+        re->tables = tables;
+
+        ptr = (const uschar *)pattern;
+        code = re->code;
+        *code = OP_BRA;
+        bracount = 0;
+        (void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, 0,
+                                                &reqchar, &countlits, &compile_block);
+        re->top_bracket = bracount;
+        re->top_backref = top_backref;
+
+        if (*errorptr == NULL && *ptr != 0)
+                *errorptr = ERR22;
+
+        *code++ = OP_END;
+        if (code - re->code > length)
+                *errorptr = ERR23;
+
+        if (top_backref > re->top_bracket)
+                *errorptr = ERR15;
+
+        if (*errorptr != NULL) {
+                (pcre_free) (re);
+          PCRE_ERROR_RETURN:
+                *erroroffset = ptr - (const uschar *)pattern;
+                return NULL;
+        }
+
+        if ((options & PCRE_ANCHORED) == 0) {
+                int temp_options = options;
+                if (is_anchored(re->code, &temp_options))
+                        re->options |= PCRE_ANCHORED;
+                else {
+                        int ch = find_firstchar(re->code, &temp_options);
+                        if (ch >= 0) {
+                                re->first_char = ch;
+                                re->options |= PCRE_FIRSTSET;
+                        }
+                        else if (is_startline(re->code))
+                                re->options |= PCRE_STARTLINE;
+                }
+        }
+
+        if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0)) {
+                re->req_char = reqchar;
+                re->options |= PCRE_REQCHSET;
+        }
 
-if (length > 65539)
-  {
-  *errorptr = ERR20;
-  return NULL;
-  }
-
-/* Compute the size of data block needed and get it, either from malloc or
-externally provided function. We specify "code[0]" in the offsetof() expression
-rather than just "code", because it has been reported that one broken compiler
-fails on "code" because it is also an independent variable. It should make no
-difference to the value of the offsetof(). */
-
-size = length + offsetof(real_pcre, code[0]);
-re = (real_pcre *)(pcre_malloc)(size);
-
-if (re == NULL)
-  {
-  *errorptr = ERR21;
-  return NULL;
-  }
-
-/* Put in the magic number, and save the size, options, and table pointer */
-
-re->magic_number = MAGIC_NUMBER;
-re->size = size;
-re->options = options;
-re->tables = tables;
-
-/* Set up a starting, non-extracting bracket, then compile the expression. On
-error, *errorptr will be set non-NULL, so we don't need to look at the result
-of the function here. */
-
-ptr = (const uschar *)pattern;
-code = re->code;
-*code = OP_BRA;
-bracount = 0;
-(void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, 0,
-  &reqchar, &countlits, &compile_block);
-re->top_bracket = bracount;
-re->top_backref = top_backref;
-
-/* If not reached end of pattern on success, there's an excess bracket. */
-
-if (*errorptr == NULL && *ptr != 0) *errorptr = 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;
-if (code - re->code > length) *errorptr = ERR23;
-
-/* Give an error if there's back reference to a non-existent capturing
-subpattern. */
-
-if (top_backref > re->top_bracket) *errorptr = ERR15;
-
-/* Failed to compile */
-
-if (*errorptr != NULL)
-  {
-  (pcre_free)(re);
-  PCRE_ERROR_RETURN:
-  *erroroffset = ptr - (const uschar *)pattern;
-  return NULL;
-  }
-
-/* If the anchored option was not passed, set 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, see if we can determine what the first character has to be, 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 ((options & PCRE_ANCHORED) == 0)
-  {
-  int temp_options = options;
-  if (is_anchored(re->code, &temp_options))
-    re->options |= PCRE_ANCHORED;
-  else
-    {
-    int ch = find_firstchar(re->code, &temp_options);
-    if (ch >= 0)
-      {
-      re->first_char = ch;
-      re->options |= PCRE_FIRSTSET;
-      }
-    else if (is_startline(re->code))
-      re->options |= PCRE_STARTLINE;
-    }
-  }
-
-/* Save the last required character if there are at least two literal
-characters on all paths, or if there is no first character setting. */
-
-if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0))
-  {
-  re->req_char = reqchar;
-  re->options |= PCRE_REQCHSET;
-  }
-
-/* Print out the compiled data for debugging */
-
-return (pcre *)re;
+        return (pcre *) re;
 }
 
-/*************************************************
-*          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 const uschar *eptr, int length, match_data *md,
-  unsigned long int ims)
+match_ref(int offset, register const uschar * eptr, int length,
+                  match_data * md, unsigned long int ims)
 {
-const uschar *p = md->start_subject + md->offset_vector[offset];
+        const uschar *p = md->start_subject + md->offset_vector[offset];
 
-/* Always fail if not enough characters left */
+        if (length > md->end_subject - eptr)
+                return FALSE;
 
-if (length > md->end_subject - eptr) return FALSE;
+        if ((ims & PCRE_CASELESS) != 0) {
+                while (length-- > 0)
+                        if (md->lcc[*p++] != md->lcc[*eptr++])
+                                return FALSE;
+        }
+        else {
+                while (length-- > 0)
+                        if (*p++ != *eptr++)
+                                return FALSE;
+        }
 
-/* Separate the caselesss case for speed */
-
-if ((ims & PCRE_CASELESS) != 0)
-  {
-  while (length-- > 0)
-    if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
-  }
-else
-  { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
-
-return TRUE;
+        return TRUE;
 }
 
-/*************************************************
-*         Match from current position            *
-*************************************************/
-
-/* On entry ecode points to the first opcode, and eptr to the first character
-in the subject string, while eptrb holds the value of eptr at the start of the
-last bracketed group - used for breaking infinite loops matching zero-length
-strings.
-
-Arguments:
-   eptr        pointer in subject
-   ecode       position in code
-   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_isgroup - this is the start of a bracketed group
-
-Returns:       TRUE if matched
-*/
-
 static BOOL
-match(register const uschar *eptr, register const uschar *ecode,
-  int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
-  int flags)
+match(register const uschar * eptr, register const uschar * ecode,
+          int offset_top, match_data * md, unsigned long int ims,
+          eptrblock * eptrb, int flags)
 {
-unsigned long int original_ims = ims;   /* Save for resetting on ')' */
-eptrblock newptrb;
+        unsigned long int original_ims = ims;
+        eptrblock newptrb;
 
-/* At the start of a bracketed group, add the current subject pointer to the
-stack of such pointers, to be re-instated at the end of the group when we hit
-the closing ket. When match() is called in other circumstances, we don't add to
-the stack. */
-
-if ((flags & match_isgroup) != 0)
-  {
-  newptrb.prev = eptrb;
-  newptrb.saved_eptr = eptr;
-  eptrb = &newptrb;
-  }
-
-/* Now start processing the operations. */
-
-for (;;)
-  {
-  int op = (int)*ecode;
-  int min, max, ctype;
-  register int i;
-  register int c;
-  BOOL minimize = FALSE;
-
-  /* Opening 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. */
-
-  if (op > OP_BRA)
-    {
-    int offset;
-    int number = op - OP_BRA;
-
-    /* For extended extraction brackets (large number), we have to fish out the
-    number from a dummy opcode at the start. */
-
-    if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
-    offset = number << 1;
-
-    if (offset < md->offset_max)
-      {
-      int save_offset1 = md->offset_vector[offset];
-      int save_offset2 = md->offset_vector[offset+1];
-      int save_offset3 = md->offset_vector[md->offset_end - number];
-
-      md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
-
-      do
-        {
-        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
-          return TRUE;
-        ecode += (ecode[1] << 8) + ecode[2];
-        }
-      while (*ecode == OP_ALT);
-
-      md->offset_vector[offset] = save_offset1;
-      md->offset_vector[offset+1] = save_offset2;
-      md->offset_vector[md->offset_end - number] = save_offset3;
-
-      return FALSE;
-      }
-
-    /* Insufficient room for saving captured contents */
-
-    else op = OP_BRA;
-    }
+        if ((flags & match_isgroup) != 0) {
+                newptrb.prev = eptrb;
+                newptrb.saved_eptr = eptr;
+                eptrb = &newptrb;
+        }
+
+        for (;;) {
+                int op = (int)*ecode;
+                int min, max, ctype;
+                register int i;
+                register int c;
+                BOOL minimize = FALSE;
+
+                if (op > OP_BRA) {
+                        int offset;
+                        int number = op - OP_BRA;
+
+                        if (number > EXTRACT_BASIC_MAX)
+                                number = (ecode[4] << 8) | ecode[5];
+                        offset = number << 1;
+
+                        if (offset < md->offset_max) {
+                                int save_offset1 = md->offset_vector[offset];
+                                int save_offset2 = md->offset_vector[offset + 1];
+                                int save_offset3 = md->offset_vector[md->offset_end - number];
+
+                                md->offset_vector[md->offset_end - number] =
+                                        eptr - md->start_subject;
+
+                                do {
+                                        if (match
+                                                (eptr, ecode + 3, offset_top, md, ims, eptrb,
+                                                 match_isgroup)) return TRUE;
+                                        ecode += (ecode[1] << 8) + ecode[2];
+                                }
+                                while (*ecode == OP_ALT);
+
+                                md->offset_vector[offset] = save_offset1;
+                                md->offset_vector[offset + 1] = save_offset2;
+                                md->offset_vector[md->offset_end - number] = save_offset3;
+
+                                return FALSE;
+                        }
+
+                        else
+                                op = OP_BRA;
+                }
+
+                switch (op) {
+                        case OP_BRA:
+
+                                do {
+                                        if (match
+                                                (eptr, ecode + 3, offset_top, md, ims, eptrb,
+                                                 match_isgroup)) return TRUE;
+                                        ecode += (ecode[1] << 8) + ecode[2];
+                                }
+                                while (*ecode == OP_ALT);
+
+                                return FALSE;
+
+                        case OP_COND:
+                                if (ecode[3] == OP_CREF) {
+                                        int offset = (ecode[4] << 9) | (ecode[5] << 1);
+                                        return match(eptr,
+                                                                 ecode +
+                                                                 ((offset
+                                                                   < offset_top
+                                                                   && md->offset_vector[offset] >=
+                                                                   0) ? 6 : 3 + (ecode[1] << 8) + ecode[2]),
+                                                                 offset_top, md, ims, eptrb, match_isgroup);
+                                }
+
+                                else {
+                                        if (match(eptr, ecode + 3, offset_top, md, ims, NULL,
+                                                          match_condassert | match_isgroup)) {
+                                                ecode += 3 + (ecode[4] << 8) + ecode[5];
+                                                while (*ecode == OP_ALT)
+                                                        ecode += (ecode[1] << 8) + ecode[2];
+                                        }
+                                        else
+                                                ecode += (ecode[1] << 8) + ecode[2];
+                                        return match(eptr, ecode + 3, offset_top, md, ims, eptrb,
+                                                                 match_isgroup);
+                                }
+
+                        case OP_CREF:
+                        case OP_BRANUMBER:
+                                ecode += 3;
+                                break;
+
+                        case OP_END:
+                                if (md->notempty && eptr == md->start_match)
+                                        return FALSE;
+                                md->end_match_ptr = eptr;
+                                md->end_offset_top = offset_top;
+                                return TRUE;
+
+                        case OP_OPT:
+                                ims = ecode[1];
+                                ecode += 2;
+
+                                break;
+
+                        case OP_ASSERT:
+                        case OP_ASSERTBACK:
+                                do {
+                                        if (match
+                                                (eptr, ecode + 3, offset_top, md, ims, NULL,
+                                                 match_isgroup)) break;
+                                        ecode += (ecode[1] << 8) + ecode[2];
+                                }
+                                while (*ecode == OP_ALT);
+                                if (*ecode == OP_KET)
+                                        return FALSE;
+
+                                if ((flags & match_condassert) != 0)
+                                        return TRUE;
+
+                                do
+                                        ecode += (ecode[1] << 8) + ecode[2];
+                                while (*ecode == OP_ALT);
+                                ecode += 3;
+                                offset_top = md->end_offset_top;
+                                continue;
+
+                        case OP_ASSERT_NOT:
+                        case OP_ASSERTBACK_NOT:
+                                do {
+                                        if (match
+                                                (eptr, ecode + 3, offset_top, md, ims, NULL,
+                                                 match_isgroup)) return FALSE;
+                                        ecode += (ecode[1] << 8) + ecode[2];
+                                }
+                                while (*ecode == OP_ALT);
 
-  /* Other types of node can be handled by a switch */
+                                if ((flags & match_condassert) != 0)
+                                        return TRUE;
 
-  switch(op)
-    {
-    case OP_BRA:     /* Non-capturing bracket: optimized */
-
-    do
-      {
-      if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
-        return TRUE;
-      ecode += (ecode[1] << 8) + ecode[2];
-      }
-    while (*ecode == OP_ALT);
-
-    return FALSE;
-
-    /* Conditional group: compilation checked that there are no more than
-    two branches. If the condition is false, skipping the first branch takes us
-    past the end if there is only one branch, but that's OK because that is
-    exactly what going to the ket would do. */
-
-    case OP_COND:
-    if (ecode[3] == OP_CREF)         /* Condition is extraction test */
-      {
-      int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */
-      return match(eptr,
-        ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
-          6 : 3 + (ecode[1] << 8) + ecode[2]),
-        offset_top, md, ims, eptrb, match_isgroup);
-      }
-
-    /* The condition is an assertion. Call match() to evaluate it - setting
-    the final argument TRUE causes it to stop at the end of an assertion. */
-
-    else
-      {
-      if (match(eptr, ecode+3, offset_top, md, ims, NULL,
-          match_condassert | match_isgroup))
-        {
-        ecode += 3 + (ecode[4] << 8) + ecode[5];
-        while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
-        }
-      else ecode += (ecode[1] << 8) + ecode[2];
-      return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
-      }
-    /* Control never reaches here */
-
-    /* Skip over conditional reference or large extraction number data if
-    encountered. */
-
-    case OP_CREF:
-    case OP_BRANUMBER:
-    ecode += 3;
-    break;
-
-    case OP_END:
-    if (md->notempty && eptr == md->start_match) return FALSE;
-    md->end_match_ptr = eptr;          /* Record where we ended */
-    md->end_offset_top = offset_top;   /* and how many extracts were taken */
-    return TRUE;
-
-    /* Change option settings */
-
-    case OP_OPT:
-    ims = ecode[1];
-    ecode += 2;
-
-    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
-      {
-      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
-      ecode += (ecode[1] << 8) + ecode[2];
-      }
-    while (*ecode == OP_ALT);
-    if (*ecode == OP_KET) return FALSE;
-
-    /* If checking an assertion for a condition, return TRUE. */
-
-    if ((flags & match_condassert) != 0) return TRUE;
-
-    /* Continue from after the assertion, updating the offsets high water
-    mark, since extracts may have been taken during the assertion. */
-
-    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
-    ecode += 3;
-    offset_top = md->end_offset_top;
-    continue;
-
-    /* Negative assertion: all branches must fail to match */
-
-    case OP_ASSERT_NOT:
-    case OP_ASSERTBACK_NOT:
-    do
-      {
-      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
-        return FALSE;
-      ecode += (ecode[1] << 8) + ecode[2];
-      }
-    while (*ecode == OP_ALT);
-
-    if ((flags & match_condassert) != 0) return TRUE;
-
-    ecode += 3;
-    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. */
+                                ecode += 3;
+                                continue;
 
-    case OP_REVERSE:
+                        case OP_REVERSE:
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-    c = (ecode[1] << 8) + ecode[2];
-    for (i = 0; i < c; i++)
-      {
-      eptr--;
-      BACKCHAR(eptr)
-      }
+                                c = (ecode[1] << 8) + ecode[2];
+                                for (i = 0; i < c; i++) {
+                                        eptr--;
+                                        BACKCHAR(eptr)
+                                }
 #else
-    eptr -= (ecode[1] << 8) + ecode[2];
+                                eptr -= (ecode[1] << 8) + ecode[2];
 #endif
 
-    if (eptr < md->start_subject) return FALSE;
-    ecode += 3;
-    break;
-
-    /* Recursion matches the current regex, nested. 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 99 such values, which
-    is a bit large to put on the stack, but using malloc for small numbers
-    seems expensive. As a compromise, the stack is used when there are fewer
-    than 16 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 15 values on the stack, and accept that the rest
-    may be wrong. */
-
-    case OP_RECURSE:
-      {
-      BOOL rc;
-      int *save;
-      int stacksave[15];
-
-      c = md->offset_max;
-
-      if (c < 16) save = stacksave; else
-        {
-        save = (int *)(pcre_malloc)((c+1) * sizeof(int));
-        if (save == NULL)
-          {
-          save = stacksave;
-          c = 15;
-          }
-        }
-
-      for (i = 1; i <= c; i++)
-        save[i] = md->offset_vector[md->offset_end - i];
-      rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb,
-        match_isgroup);
-      for (i = 1; i <= c; i++)
-        md->offset_vector[md->offset_end - i] = save[i];
-      if (save != stacksave) (pcre_free)(save);
-      if (!rc) return FALSE;
-
-      /* In case the recursion has set more capturing values, save the final
-      number, then move along the subject till after the recursive match,
-      and advance one byte in the pattern code. */
-
-      offset_top = md->end_offset_top;
-      eptr = md->end_match_ptr;
-      ecode++;
-      }
-    break;
-
-    /* "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. 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. */
-
-    case OP_ONCE:
-      {
-      const uschar *prev = ecode;
-      const uschar *saved_eptr = eptr;
-
-      do
-        {
-        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
-          break;
-        ecode += (ecode[1] << 8) + ecode[2];
-        }
-      while (*ecode == OP_ALT);
-
-      /* If hit the end of the group (which could be repeated), fail */
-
-      if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
-
-      /* Continue as from after the assertion, updating the offsets high water
-      mark, since extracts may have been taken. */
-
-      do ecode += (ecode[1] << 8) + ecode[2]; 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 += 3;
-        break;
-        }
-
-      /* The repeating kets try the rest of the pattern or restart from the
-      preceding bracket, in the appropriate order. We need to reset any options
-      that changed within the bracket before re-running it, so check the next
-      opcode. */
-
-      if (ecode[3] == OP_OPT)
-        {
-        ims = (ims & ~PCRE_IMS) | ecode[4];
-
-        }
-
-      if (*ecode == OP_KETRMIN)
-        {
-        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
-            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
-              return TRUE;
-        }
-      else  /* OP_KETRMAX */
-        {
-        if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
-            match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
-        }
-      }
-    return FALSE;
-
-    /* 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 += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
-    break;
-
-    /* BRAZERO and BRAMINZERO 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 ()? 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:
-      {
-      const uschar *next = ecode+1;
-      if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
-        return TRUE;
-      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
-      ecode = next + 3;
-      }
-    break;
-
-    case OP_BRAMINZERO:
-      {
-      const uschar *next = ecode+1;
-      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
-      if (match(eptr, next+3, offset_top, md, ims, eptrb, match_isgroup))
-        return TRUE;
-      ecode++;
-      }
-    break;
-
-    case OP_KET:
-    case OP_KETRMIN:
-    case OP_KETRMAX:
-      {
-      const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
-      const uschar *saved_eptr = eptrb->saved_eptr;
-
-      eptrb = eptrb->prev;    /* Back up the stack of bracket start pointers */
-
-      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;
-        return TRUE;
-        }
-
-      /* In all other cases except a conditional group 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. */
-
-      if (*prev != OP_COND)
-        {
-        int offset;
-        int number = *prev - OP_BRA;
-
-        /* For extended extraction brackets (large number), we have to fish out
-        the number from a dummy opcode at the start. */
-
-        if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
-        offset = number << 1;
-
-        if (number > 0)
-          {
-          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] = eptr - md->start_subject;
-            if (offset_top <= offset) offset_top = offset + 2;
-            }
-          }
-        }
-
-      /* Reset the value of the ims flags, in case they got changed during
-      the group. */
-
-      ims = original_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 += 3;
-        break;
-        }
-
-      /* The repeating kets try the rest of the pattern or restart from the
-      preceding bracket, in the appropriate order. */
-
-      if (*ecode == OP_KETRMIN)
-        {
-        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
-            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
-              return TRUE;
-        }
-      else  /* OP_KETRMAX */
-        {
-        if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
-            match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
-        }
-      }
-    return FALSE;
-
-    /* Start of subject unless notbol, or after internal newline if multiline */
-
-    case OP_CIRC:
-    if (md->notbol && eptr == md->start_subject) return FALSE;
-    if ((ims & PCRE_MULTILINE) != 0)
-      {
-      if (eptr != md->start_subject && eptr[-1] != '\n') return FALSE;
-      ecode++;
-      break;
-      }
-    /* ... else fall through */
-
-    /* Start of subject assertion */
-
-    case OP_SOD:
-    if (eptr != md->start_subject) return FALSE;
-    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 (*eptr != '\n') return FALSE; }
-        else { if (md->noteol) return FALSE; }
-      ecode++;
-      break;
-      }
-    else
-      {
-      if (md->noteol) return FALSE;
-      if (!md->endonly)
-        {
-        if (eptr < md->end_subject - 1 ||
-           (eptr == md->end_subject - 1 && *eptr != '\n')) return FALSE;
-
-        ecode++;
-        break;
-        }
-      }
-    /* ... else fall through */
-
-    case OP_EOD:
-    if (eptr < md->end_subject) return FALSE;
-    ecode++;
-    break;
-
-    case OP_EODN:
-    if (eptr < md->end_subject - 1 ||
-       (eptr == md->end_subject - 1 && *eptr != '\n')) return FALSE;
-    ecode++;
-    break;
-
-    /* Word boundary assertions */
-
-    case OP_NOT_WORD_BOUNDARY:
-    case OP_WORD_BOUNDARY:
-      {
-      BOOL prev_is_word = (eptr != md->start_subject) &&
-        ((md->ctypes[eptr[-1]] & ctype_word) != 0);
-      BOOL cur_is_word = (eptr < md->end_subject) &&
-        ((md->ctypes[*eptr] & ctype_word) != 0);
-      if ((*ecode++ == OP_WORD_BOUNDARY)?
-           cur_is_word == prev_is_word : cur_is_word != prev_is_word)
-        return FALSE;
-      }
-    break;
-
-    /* Match a single character type; inline for speed */
-
-    case OP_ANY:
-    if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n')
-      return FALSE;
-    if (eptr++ >= md->end_subject) return FALSE;
+                                if (eptr < md->start_subject)
+                                        return FALSE;
+                                ecode += 3;
+                                break;
+
+                        case OP_RECURSE:
+                                {
+                                        BOOL rc;
+                                        int *save;
+                                        int stacksave[15];
+
+                                        c = md->offset_max;
+
+                                        if (c < 16)
+                                                save = stacksave;
+                                        else {
+                                                save = (int *)(pcre_malloc) ((c + 1) * sizeof (int));
+                                                if (save == NULL) {
+                                                        save = stacksave;
+                                                        c = 15;
+                                                }
+                                        }
+
+                                        for (i = 1; i <= c; i++)
+                                                save[i] = md->offset_vector[md->offset_end - i];
+                                        rc =
+                                                match(eptr, md->start_pattern, offset_top, md, ims,
+                                                          eptrb, match_isgroup);
+                                        for (i = 1; i <= c; i++)
+                                                md->offset_vector[md->offset_end - i] = save[i];
+                                        if (save != stacksave)
+                                                (pcre_free) (save);
+                                        if (!rc)
+                                                return FALSE;
+
+                                        offset_top = md->end_offset_top;
+                                        eptr = md->end_match_ptr;
+                                        ecode++;
+                                }
+                                break;
+
+                        case OP_ONCE:
+                                {
+                                        const uschar *prev = ecode;
+                                        const uschar *saved_eptr = eptr;
+
+                                        do {
+                                                if (match
+                                                        (eptr, ecode + 3, offset_top, md, ims, eptrb,
+                                                         match_isgroup)) break;
+                                                ecode += (ecode[1] << 8) + ecode[2];
+                                        }
+                                        while (*ecode == OP_ALT);
+
+                                        if (*ecode != OP_ONCE && *ecode != OP_ALT)
+                                                return FALSE;
+
+                                        do
+                                                ecode += (ecode[1] << 8) + ecode[2];
+                                        while (*ecode == OP_ALT);
+
+                                        offset_top = md->end_offset_top;
+                                        eptr = md->end_match_ptr;
+
+                                        if (*ecode == OP_KET || eptr == saved_eptr) {
+                                                ecode += 3;
+                                                break;
+                                        }
+
+                                        if (ecode[3] == OP_OPT) {
+                                                ims = (ims & ~PCRE_IMS) | ecode[4];
+
+                                        }
+
+                                        if (*ecode == OP_KETRMIN) {
+                                                if (match
+                                                        (eptr, ecode + 3, offset_top, md, ims, eptrb, 0)
+                                                        || match(eptr, prev, offset_top, md, ims, eptrb,
+                                                                         match_isgroup)) return TRUE;
+                                        }
+                                        else {
+                                                if (match
+                                                        (eptr, prev, offset_top, md, ims, eptrb,
+                                                         match_isgroup)
+                                                        || match(eptr, ecode + 3, offset_top, md, ims,
+                                                                         eptrb, 0))
+                                                        return TRUE;
+                                        }
+                                }
+                                return FALSE;
+
+                        case OP_ALT:
+                                do
+                                        ecode += (ecode[1] << 8) + ecode[2];
+                                while (*ecode == OP_ALT);
+                                break;
+
+                        case OP_BRAZERO:
+                                {
+                                        const uschar *next = ecode + 1;
+                                        if (match
+                                                (eptr, next, offset_top, md, ims, eptrb,
+                                                 match_isgroup)) return TRUE;
+                                        do
+                                                next += (next[1] << 8) + next[2];
+                                        while (*next == OP_ALT);
+                                        ecode = next + 3;
+                                }
+                                break;
+
+                        case OP_BRAMINZERO:
+                                {
+                                        const uschar *next = ecode + 1;
+                                        do
+                                                next += (next[1] << 8) + next[2];
+                                        while (*next == OP_ALT);
+                                        if (match
+                                                (eptr, next + 3, offset_top, md, ims, eptrb,
+                                                 match_isgroup)) return TRUE;
+                                        ecode++;
+                                }
+                                break;
+
+                        case OP_KET:
+                        case OP_KETRMIN:
+                        case OP_KETRMAX:
+                                {
+                                        const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
+                                        const uschar *saved_eptr = eptrb->saved_eptr;
+
+                                        eptrb = eptrb->prev;
+
+                                        if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
+                                                *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT
+                                                || *prev == OP_ONCE) {
+                                                md->end_match_ptr = eptr;
+                                                md->end_offset_top = offset_top;
+                                                return TRUE;
+                                        }
+
+                                        if (*prev != OP_COND) {
+                                                int offset;
+                                                int number = *prev - OP_BRA;
+
+                                                if (number > EXTRACT_BASIC_MAX)
+                                                        number = (prev[4] << 8) | prev[5];
+                                                offset = number << 1;
+
+                                                if (number > 0) {
+                                                        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] =
+                                                                        eptr - md->start_subject;
+                                                                if (offset_top <= offset)
+                                                                        offset_top = offset + 2;
+                                                        }
+                                                }
+                                        }
+
+                                        ims = original_ims;
+
+                                        if (*ecode == OP_KET || eptr == saved_eptr) {
+                                                ecode += 3;
+                                                break;
+                                        }
+
+                                        if (*ecode == OP_KETRMIN) {
+                                                if (match
+                                                        (eptr, ecode + 3, offset_top, md, ims, eptrb, 0)
+                                                        || match(eptr, prev, offset_top, md, ims, eptrb,
+                                                                         match_isgroup)) return TRUE;
+                                        }
+                                        else {
+                                                if (match
+                                                        (eptr, prev, offset_top, md, ims, eptrb,
+                                                         match_isgroup)
+                                                        || match(eptr, ecode + 3, offset_top, md, ims,
+                                                                         eptrb, 0))
+                                                        return TRUE;
+                                        }
+                                }
+                                return FALSE;
+
+                        case OP_CIRC:
+                                if (md->notbol && eptr == md->start_subject)
+                                        return FALSE;
+                                if ((ims & PCRE_MULTILINE) != 0) {
+                                        if (eptr != md->start_subject && eptr[-1] != '\n')
+                                                return FALSE;
+                                        ecode++;
+                                        break;
+                                }
+
+                        case OP_SOD:
+                                if (eptr != md->start_subject)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_DOLL:
+                                if ((ims & PCRE_MULTILINE) != 0) {
+                                        if (eptr < md->end_subject) {
+                                                if (*eptr != '\n')
+                                                        return FALSE;
+                                        }
+                                        else {
+                                                if (md->noteol)
+                                                        return FALSE;
+                                        }
+                                        ecode++;
+                                        break;
+                                }
+                                else {
+                                        if (md->noteol)
+                                                return FALSE;
+                                        if (!md->endonly) {
+                                                if (eptr < md->end_subject - 1 ||
+                                                        (eptr == md->end_subject - 1 && *eptr != '\n'))
+                                                        return FALSE;
+
+                                                ecode++;
+                                                break;
+                                        }
+                                }
+                        case OP_EOD:
+                                if (eptr < md->end_subject)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_EODN:
+                                if (eptr < md->end_subject - 1 ||
+                                        (eptr == md->end_subject - 1 && *eptr != '\n'))
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_NOT_WORD_BOUNDARY:
+                        case OP_WORD_BOUNDARY:
+                                {
+                                        BOOL prev_is_word = (eptr != md->start_subject) &&
+                                                ((md->ctypes[eptr[-1]] & ctype_word) != 0);
+                                        BOOL cur_is_word = (eptr < md->end_subject) &&
+                                                ((md->ctypes[*eptr] & ctype_word) != 0);
+                                        if ((*ecode++ == OP_WORD_BOUNDARY) ?
+                                                cur_is_word == prev_is_word : cur_is_word !=
+                                                prev_is_word) return FALSE;
+                                }
+                                break;
+
+                        case OP_ANY:
+                                if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject
+                                        && *eptr == '\n')
+                                        return FALSE;
+                                if (eptr++ >= md->end_subject)
+                                        return FALSE;
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-    if (md->utf8)
-      while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+                                if (md->utf8)
+                                        while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80)
+                                                eptr++;
 #endif
-    ecode++;
-    break;
-
-    case OP_NOT_DIGIT:
-    if (eptr >= md->end_subject ||
-       (md->ctypes[*eptr++] & ctype_digit) != 0)
-      return FALSE;
-    ecode++;
-    break;
-
-    case OP_DIGIT:
-    if (eptr >= md->end_subject ||
-       (md->ctypes[*eptr++] & ctype_digit) == 0)
-      return FALSE;
-    ecode++;
-    break;
-
-    case OP_NOT_WHITESPACE:
-    if (eptr >= md->end_subject ||
-       (md->ctypes[*eptr++] & ctype_space) != 0)
-      return FALSE;
-    ecode++;
-    break;
-
-    case OP_WHITESPACE:
-    if (eptr >= md->end_subject ||
-       (md->ctypes[*eptr++] & ctype_space) == 0)
-      return FALSE;
-    ecode++;
-    break;
-
-    case OP_NOT_WORDCHAR:
-    if (eptr >= md->end_subject ||
-       (md->ctypes[*eptr++] & ctype_word) != 0)
-      return FALSE;
-    ecode++;
-    break;
-
-    case OP_WORDCHAR:
-    if (eptr >= md->end_subject ||
-       (md->ctypes[*eptr++] & ctype_word) == 0)
-      return FALSE;
-    ecode++;
-    break;
-
-    /* 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:
-      {
-      int length;
-      int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
-      ecode += 3;                                     /* Advance past item */
-
-      /* If the reference is unset, 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. */
-
-      length = (offset >= offset_top || md->offset_vector[offset] < 0)?
-        md->end_subject - eptr + 1 :
-        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 = (ecode[1] << 8) + ecode[2];
-        max = (ecode[3] << 8) + ecode[4];
-        if (max == 0) max = INT_MAX;
-        ecode += 5;
-        break;
-
-        default:               /* No repeat follows */
-        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
-        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)) return FALSE;
-        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 (i = min;; i++)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          if (i >= max || !match_ref(offset, eptr, length, md, ims))
-            return FALSE;
-          eptr += length;
-          }
-        /* Control never gets here */
-        }
-
-      /* If maximizing, find the longest string and work backwards */
-
-      else
-        {
-        const uschar *pp = eptr;
-        for (i = min; i < max; i++)
-          {
-          if (!match_ref(offset, eptr, length, md, ims)) break;
-          eptr += length;
-          }
-        while (eptr >= pp)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          eptr -= length;
-          }
-        return FALSE;
-        }
-      }
-    /* Control never gets here */
-
-    /* Match a character class, possibly repeatedly. 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_CLASS:
-      {
-      const uschar *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 = (ecode[1] << 8) + ecode[2];
-        max = (ecode[3] << 8) + ecode[4];
-        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) return FALSE;
-        GETCHARINC(c, eptr)         /* Get character; increment eptr */
+                                ecode++;
+                                break;
 
+                        case OP_NOT_DIGIT:
+                                if (eptr >= md->end_subject ||
+                                        (md->ctypes[*eptr++] & ctype_digit) != 0)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_DIGIT:
+                                if (eptr >= md->end_subject ||
+                                        (md->ctypes[*eptr++] & ctype_digit) == 0)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_NOT_WHITESPACE:
+                                if (eptr >= md->end_subject ||
+                                        (md->ctypes[*eptr++] & ctype_space) != 0)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_WHITESPACE:
+                                if (eptr >= md->end_subject ||
+                                        (md->ctypes[*eptr++] & ctype_space) == 0)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_NOT_WORDCHAR:
+                                if (eptr >= md->end_subject ||
+                                        (md->ctypes[*eptr++] & ctype_word) != 0)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_WORDCHAR:
+                                if (eptr >= md->end_subject ||
+                                        (md->ctypes[*eptr++] & ctype_word) == 0)
+                                        return FALSE;
+                                ecode++;
+                                break;
+
+                        case OP_REF:
+                                {
+                                        int length;
+                                        int offset = (ecode[1] << 9) | (ecode[2] << 1);
+                                        ecode += 3;
+
+                                        length = (offset >= offset_top
+                                                          || md->offset_vector[offset] <
+                                                          0) ? md->end_subject - eptr +
+                                                1 : md->offset_vector[offset + 1] -
+                                                md->offset_vector[offset];
+
+                                        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];
+                                                        max = rep_max[c];
+                                                        if (max == 0)
+                                                                max = INT_MAX;
+                                                        break;
+
+                                                case OP_CRRANGE:
+                                                case OP_CRMINRANGE:
+                                                        minimize = (*ecode == OP_CRMINRANGE);
+                                                        min = (ecode[1] << 8) + ecode[2];
+                                                        max = (ecode[3] << 8) + ecode[4];
+                                                        if (max == 0)
+                                                                max = INT_MAX;
+                                                        ecode += 5;
+                                                        break;
+
+                                                default:
+                                                        if (!match_ref(offset, eptr, length, md, ims))
+                                                                return FALSE;
+                                                        eptr += length;
+                                                        continue;
+                                        }
+
+                                        if (length == 0)
+                                                continue;
+
+                                        for (i = 1; i <= min; i++) {
+                                                if (!match_ref(offset, eptr, length, md, ims))
+                                                        return FALSE;
+                                                eptr += length;
+                                        }
+
+                                        if (min == max)
+                                                continue;
+
+                                        if (minimize) {
+                                                for (i = min;; i++) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        if (i >= max
+                                                                || !match_ref(offset, eptr, length, md, ims))
+                                                                return FALSE;
+                                                        eptr += length;
+                                                }
+                                        }
+
+                                        else {
+                                                const uschar *pp = eptr;
+                                                for (i = min; i < max; i++) {
+                                                        if (!match_ref(offset, eptr, length, md, ims))
+                                                                break;
+                                                        eptr += length;
+                                                }
+                                                while (eptr >= pp) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        eptr -= length;
+                                                }
+                                                return FALSE;
+                                        }
+                                }
+
+                        case OP_CLASS:
+                                {
+                                        const uschar *data = ecode + 1;
+                                        ecode += 33;
+
+                                        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];
+                                                        max = rep_max[c];
+                                                        if (max == 0)
+                                                                max = INT_MAX;
+                                                        break;
+
+                                                case OP_CRRANGE:
+                                                case OP_CRMINRANGE:
+                                                        minimize = (*ecode == OP_CRMINRANGE);
+                                                        min = (ecode[1] << 8) + ecode[2];
+                                                        max = (ecode[3] << 8) + ecode[4];
+                                                        if (max == 0)
+                                                                max = INT_MAX;
+                                                        ecode += 5;
+                                                        break;
+
+                                                default:
+                                                        min = max = 1;
+                                                        break;
+                                        }
+
+                                        for (i = 1; i <= min; i++) {
+                                                if (eptr >= md->end_subject)
+                                                        return FALSE;
+                                                GETCHARINC(c, eptr)
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-        /* We do not yet support class members > 255 */
-        if (c > 255) return FALSE;
+                                                        if (c > 255)
+                                                        return FALSE;
 #endif
 
-        if ((data[c/8] & (1 << (c&7))) != 0) continue;
-        return FALSE;
-        }
-
-      /* 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 (i = min;; i++)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          if (i >= max || eptr >= md->end_subject) return FALSE;
-          GETCHARINC(c, eptr)       /* Get character; increment eptr */
-
+                                                if ((data[c / 8] & (1 << (c & 7))) != 0)
+                                                        continue;
+                                                return FALSE;
+                                        }
+
+                                        if (min == max)
+                                                continue;
+
+                                        if (minimize) {
+                                                for (i = min;; i++) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        if (i >= max || eptr >= md->end_subject)
+                                                                return FALSE;
+                                                        GETCHARINC(c, eptr)
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-          /* We do not yet support class members > 255 */
-          if (c > 255) return FALSE;
+                                                                if (c > 255)
+                                                                return FALSE;
 #endif
-          if ((data[c/8] & (1 << (c&7))) != 0) continue;
-          return FALSE;
-          }
-        /* Control never gets here */
-        }
-
-      /* If maximizing, find the longest possible run, then work backwards. */
-
-      else
-        {
-        const uschar *pp = eptr;
-        int len = 1;
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject) break;
-          GETCHARLEN(c, eptr, len)  /* Get character, set length if UTF-8 */
-
+                                                        if ((data[c / 8] & (1 << (c & 7))) != 0)
+                                                                continue;
+                                                        return FALSE;
+                                                }
+                                        }
+
+                                        else {
+                                                const uschar *pp = eptr;
+                                                int len = 1;
+                                                for (i = min; i < max; i++) {
+                                                        if (eptr >= md->end_subject)
+                                                                break;
+                                                        GETCHARLEN(c, eptr, len)
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-          /* We do not yet support class members > 255 */
-          if (c > 255) break;
+                                                                if (c > 255)
+                                                                break;
 #endif
-          if ((data[c/8] & (1 << (c&7))) == 0) break;
-          eptr += len;
-          }
-
-        while (eptr >= pp)
-          {
-          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
+                                                        if ((data[c / 8] & (1 << (c & 7))) == 0)
+                                                                break;
+                                                        eptr += len;
+                                                }
+
+                                                while (eptr >= pp) {
+                                                        if (match
+                                                                (eptr--, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-          BACKCHAR(eptr)
+                                                        BACKCHAR(eptr)
 #endif
-          }
-        return FALSE;
-        }
-      }
-    /* Control never gets here */
-
-    /* Match a run of characters */
-
-    case OP_CHARS:
-      {
-      register int length = ecode[1];
-      ecode += 2;
-
-      if (length > md->end_subject - eptr) return FALSE;
-      if ((ims & PCRE_CASELESS) != 0)
-        {
-        while (length-- > 0)
-          if (md->lcc[*ecode++] != md->lcc[*eptr++])
-            return FALSE;
-        }
-      else
-        {
-        while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
-        }
-      }
-    break;
-
-    /* Match a single character repeatedly; different opcodes share code. */
-
-    case OP_EXACT:
-    min = max = (ecode[1] << 8) + ecode[2];
-    ecode += 3;
-    goto REPEATCHAR;
-
-    case OP_UPTO:
-    case OP_MINUPTO:
-    min = 0;
-    max = (ecode[1] << 8) + ecode[2];
-    minimize = *ecode == OP_MINUPTO;
-    ecode += 3;
-    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. We can give
-    up quickly if there are fewer than the minimum number of characters left in
-    the subject. */
-
-    REPEATCHAR:
-    if (min > md->end_subject - eptr) return FALSE;
-    c = *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. */
-
-    if ((ims & PCRE_CASELESS) != 0)
-      {
-      c = md->lcc[c];
-      for (i = 1; i <= min; i++)
-        if (c != md->lcc[*eptr++]) return FALSE;
-      if (min == max) continue;
-      if (minimize)
-        {
-        for (i = min;; i++)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          if (i >= max || eptr >= md->end_subject ||
-              c != md->lcc[*eptr++])
-            return FALSE;
-          }
-        /* Control never gets here */
-        }
-      else
-        {
-        const uschar *pp = eptr;
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
-          eptr++;
-          }
-        while (eptr >= pp)
-          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-        return FALSE;
-        }
-      /* Control never gets here */
-      }
-
-    /* Caseful comparisons */
-
-    else
-      {
-      for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
-      if (min == max) continue;
-      if (minimize)
-        {
-        for (i = min;; i++)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
-          }
-        /* Control never gets here */
-        }
-      else
-        {
-        const uschar *pp = eptr;
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || c != *eptr) break;
-          eptr++;
-          }
-        while (eptr >= pp)
-         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
-           return TRUE;
-        return FALSE;
-        }
-      }
-    /* Control never gets here */
-
-    /* Match a negated single character */
-
-    case OP_NOT:
-    if (eptr >= md->end_subject) return FALSE;
-    ecode++;
-    if ((ims & PCRE_CASELESS) != 0)
-      {
-      if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
-      }
-    else
-      {
-      if (*ecode++ == *eptr++) return FALSE;
-      }
-    break;
-
-    /* Match a negated single 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 = (ecode[1] << 8) + ecode[2];
-    ecode += 3;
-    goto REPEATNOTCHAR;
-
-    case OP_NOTUPTO:
-    case OP_NOTMINUPTO:
-    min = 0;
-    max = (ecode[1] << 8) + ecode[2];
-    minimize = *ecode == OP_NOTMINUPTO;
-    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-character matches. We can give
-    up quickly if there are fewer than the minimum number of characters left in
-    the subject. */
-
-    REPEATNOTCHAR:
-    if (min > md->end_subject - eptr) return FALSE;
-    c = *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. */
-
-    if ((ims & PCRE_CASELESS) != 0)
-      {
-      c = md->lcc[c];
-      for (i = 1; i <= min; i++)
-        if (c == md->lcc[*eptr++]) return FALSE;
-      if (min == max) continue;
-      if (minimize)
-        {
-        for (i = min;; i++)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          if (i >= max || eptr >= md->end_subject ||
-              c == md->lcc[*eptr++])
-            return FALSE;
-          }
-        /* Control never gets here */
-        }
-      else
-        {
-        const uschar *pp = eptr;
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
-          eptr++;
-          }
-        while (eptr >= pp)
-          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-        return FALSE;
-        }
-      /* Control never gets here */
-      }
-
-    /* Caseful comparisons */
-
-    else
-      {
-      for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
-      if (min == max) continue;
-      if (minimize)
-        {
-        for (i = min;; i++)
-          {
-          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
-            return TRUE;
-          if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
-          }
-        /* Control never gets here */
-        }
-      else
-        {
-        const uschar *pp = eptr;
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || c == *eptr) break;
-          eptr++;
-          }
-        while (eptr >= pp)
-         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
-           return TRUE;
-        return FALSE;
-        }
-      }
-    /* 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 = (ecode[1] << 8) + ecode[2];
-    minimize = TRUE;
-    ecode += 3;
-    goto REPEATTYPE;
-
-    case OP_TYPEUPTO:
-    case OP_TYPEMINUPTO:
-    min = 0;
-    max = (ecode[1] << 8) + ecode[2];
-    minimize = *ecode == OP_TYPEMINUPTO;
-    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 */
-
-    REPEATTYPE:
-    ctype = *ecode++;      /* Code for the character type */
-
-    /* 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). Also we can test that there are at least
-    the minimum number of bytes before we start, except when doing '.' in
-    UTF8 mode. Leave the test in in all cases; in the special case we have
-    to test after each character. */
-
-    if (min > md->end_subject - eptr) return FALSE;
-    if (min > 0) switch(ctype)
-      {
-      case OP_ANY:
+                                                }
+                                                return FALSE;
+                                        }
+                                }
+
+                        case OP_CHARS:
+                                {
+                                        register int length = ecode[1];
+                                        ecode += 2;
+
+                                        if (length > md->end_subject - eptr)
+                                                return FALSE;
+                                        if ((ims & PCRE_CASELESS) != 0) {
+                                                while (length-- > 0)
+                                                        if (md->lcc[*ecode++] != md->lcc[*eptr++])
+                                                                return FALSE;
+                                        }
+                                        else {
+                                                while (length-- > 0)
+                                                        if (*ecode++ != *eptr++)
+                                                                return FALSE;
+                                        }
+                                }
+                                break;
+
+                        case OP_EXACT:
+                                min = max = (ecode[1] << 8) + ecode[2];
+                                ecode += 3;
+                                goto REPEATCHAR;
+
+                        case OP_UPTO:
+                        case OP_MINUPTO:
+                                min = 0;
+                                max = (ecode[1] << 8) + ecode[2];
+                                minimize = *ecode == OP_MINUPTO;
+                                ecode += 3;
+                                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];
+                                max = rep_max[c];
+                                if (max == 0)
+                                        max = INT_MAX;
+
+                          REPEATCHAR:
+                                if (min > md->end_subject - eptr)
+                                        return FALSE;
+                                c = *ecode++;
+
+                                if ((ims & PCRE_CASELESS) != 0) {
+                                        c = md->lcc[c];
+                                        for (i = 1; i <= min; i++)
+                                                if (c != md->lcc[*eptr++])
+                                                        return FALSE;
+                                        if (min == max)
+                                                continue;
+                                        if (minimize) {
+                                                for (i = min;; i++) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        if (i >= max || eptr >= md->end_subject
+                                                                || c != md->lcc[*eptr++])
+                                                                return FALSE;
+                                                }
+                                        }
+                                        else {
+                                                const uschar *pp = eptr;
+                                                for (i = min; i < max; i++) {
+                                                        if (eptr >= md->end_subject
+                                                                || c != md->lcc[*eptr]) break;
+                                                        eptr++;
+                                                }
+                                                while (eptr >= pp)
+                                                        if (match
+                                                                (eptr--, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                return FALSE;
+                                        }
+                                }
+
+                                else {
+                                        for (i = 1; i <= min; i++)
+                                                if (c != *eptr++)
+                                                        return FALSE;
+                                        if (min == max)
+                                                continue;
+                                        if (minimize) {
+                                                for (i = min;; i++) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        if (i >= max || eptr >= md->end_subject
+                                                                || c != *eptr++)
+                                                                return FALSE;
+                                                }
+                                        }
+                                        else {
+                                                const uschar *pp = eptr;
+                                                for (i = min; i < max; i++) {
+                                                        if (eptr >= md->end_subject || c != *eptr)
+                                                                break;
+                                                        eptr++;
+                                                }
+                                                while (eptr >= pp)
+                                                        if (match
+                                                                (eptr--, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                return FALSE;
+                                        }
+                                }
+
+                        case OP_NOT:
+                                if (eptr >= md->end_subject)
+                                        return FALSE;
+                                ecode++;
+                                if ((ims & PCRE_CASELESS) != 0) {
+                                        if (md->lcc[*ecode++] == md->lcc[*eptr++])
+                                                return FALSE;
+                                }
+                                else {
+                                        if (*ecode++ == *eptr++)
+                                                return FALSE;
+                                }
+                                break;
+
+                        case OP_NOTEXACT:
+                                min = max = (ecode[1] << 8) + ecode[2];
+                                ecode += 3;
+                                goto REPEATNOTCHAR;
+
+                        case OP_NOTUPTO:
+                        case OP_NOTMINUPTO:
+                                min = 0;
+                                max = (ecode[1] << 8) + ecode[2];
+                                minimize = *ecode == OP_NOTMINUPTO;
+                                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];
+                                max = rep_max[c];
+                                if (max == 0)
+                                        max = INT_MAX;
+
+                          REPEATNOTCHAR:
+                                if (min > md->end_subject - eptr)
+                                        return FALSE;
+                                c = *ecode++;
+
+                                if ((ims & PCRE_CASELESS) != 0) {
+                                        c = md->lcc[c];
+                                        for (i = 1; i <= min; i++)
+                                                if (c == md->lcc[*eptr++])
+                                                        return FALSE;
+                                        if (min == max)
+                                                continue;
+                                        if (minimize) {
+                                                for (i = min;; i++) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        if (i >= max || eptr >= md->end_subject
+                                                                || c == md->lcc[*eptr++])
+                                                                return FALSE;
+                                                }
+                                        }
+                                        else {
+                                                const uschar *pp = eptr;
+                                                for (i = min; i < max; i++) {
+                                                        if (eptr >= md->end_subject
+                                                                || c == md->lcc[*eptr]) break;
+                                                        eptr++;
+                                                }
+                                                while (eptr >= pp)
+                                                        if (match
+                                                                (eptr--, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                return FALSE;
+                                        }
+                                }
+
+                                else {
+                                        for (i = 1; i <= min; i++)
+                                                if (c == *eptr++)
+                                                        return FALSE;
+                                        if (min == max)
+                                                continue;
+                                        if (minimize) {
+                                                for (i = min;; i++) {
+                                                        if (match
+                                                                (eptr, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                        if (i >= max || eptr >= md->end_subject
+                                                                || c == *eptr++)
+                                                                return FALSE;
+                                                }
+                                        }
+                                        else {
+                                                const uschar *pp = eptr;
+                                                for (i = min; i < max; i++) {
+                                                        if (eptr >= md->end_subject || c == *eptr)
+                                                                break;
+                                                        eptr++;
+                                                }
+                                                while (eptr >= pp)
+                                                        if (match
+                                                                (eptr--, ecode, offset_top, md, ims, eptrb,
+                                                                 0)) return TRUE;
+                                                return FALSE;
+                                        }
+                                }
+
+                        case OP_TYPEEXACT:
+                                min = max = (ecode[1] << 8) + ecode[2];
+                                minimize = TRUE;
+                                ecode += 3;
+                                goto REPEATTYPE;
+
+                        case OP_TYPEUPTO:
+                        case OP_TYPEMINUPTO:
+                                min = 0;
+                                max = (ecode[1] << 8) + ecode[2];
+                                minimize = *ecode == OP_TYPEMINUPTO;
+                                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];
+                                max = rep_max[c];
+                                if (max == 0)
+                                        max = INT_MAX;
+
+                          REPEATTYPE:
+                                ctype = *ecode++;
+
+                                if (min > md->end_subject - eptr)
+                                        return FALSE;
+                                if (min > 0)
+                                        switch (ctype) {
+                                                case OP_ANY:
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-      if (md->utf8)
-        {
-        for (i = 1; i <= min; i++)
-          {
-          if (eptr >= md->end_subject ||
-             (*eptr++ == '\n' && (ims & PCRE_DOTALL) == 0))
-            return FALSE;
-          while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
-          }
-        break;
-        }
+                                                        if (md->utf8) {
+                                                                for (i = 1; i <= min; i++) {
+                                                                        if (eptr >= md->end_subject ||
+                                                                                (*eptr++ == '\n'
+                                                                                 && (ims & PCRE_DOTALL) == 0))
+                                                                                return FALSE;
+                                                                        while (eptr < md->end_subject
+                                                                                   && (*eptr & 0xc0) == 0x80)
+                                                                                eptr++;
+                                                                }
+                                                                break;
+                                                        }
 #endif
-      /* Non-UTF8 can be faster */
-      if ((ims & PCRE_DOTALL) == 0)
-        { for (i = 1; i <= min; i++) if (*eptr++ == '\n') return FALSE; }
-      else eptr += min;
-      break;
-
-      case OP_NOT_DIGIT:
-      for (i = 1; i <= min; i++)
-        if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
-      break;
-
-      case OP_DIGIT:
-      for (i = 1; i <= min; i++)
-        if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
-      break;
-
-      case OP_NOT_WHITESPACE:
-      for (i = 1; i <= min; i++)
-        if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
-      break;
-
-      case OP_WHITESPACE:
-      for (i = 1; i <= min; i++)
-        if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
-      break;
-
-      case OP_NOT_WORDCHAR:
-      for (i = 1; i <= min; i++)
-        if ((md->ctypes[*eptr++] & ctype_word) != 0)
-          return FALSE;
-      break;
-
-      case OP_WORDCHAR:
-      for (i = 1; i <= min; i++)
-        if ((md->ctypes[*eptr++] & ctype_word) == 0)
-          return FALSE;
-      break;
-      }
-
-    /* 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. */
-
-    if (minimize)
-      {
-      for (i = min;; i++)
-        {
-        if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
-        if (i >= max || eptr >= md->end_subject) return FALSE;
-
-        c = *eptr++;
-        switch(ctype)
-          {
-          case OP_ANY:
-          if ((ims & PCRE_DOTALL) == 0 && c == '\n') return FALSE;
+                                                        if ((ims & PCRE_DOTALL) == 0) {
+                                                                for (i = 1; i <= min; i++)
+                                                                        if (*eptr++ == '\n')
+                                                                                return FALSE;
+                                                        }
+                                                        else
+                                                                eptr += min;
+                                                        break;
+
+                                                case OP_NOT_DIGIT:
+                                                        for (i = 1; i <= min; i++)
+                                                                if ((md->ctypes[*eptr++] & ctype_digit) != 0)
+                                                                        return FALSE;
+                                                        break;
+
+                                                case OP_DIGIT:
+                                                        for (i = 1; i <= min; i++)
+                                                                if ((md->ctypes[*eptr++] & ctype_digit) == 0)
+                                                                        return FALSE;
+                                                        break;
+
+                                                case OP_NOT_WHITESPACE:
+                                                        for (i = 1; i <= min; i++)
+                                                                if ((md->ctypes[*eptr++] & ctype_space) != 0)
+                                                                        return FALSE;
+                                                        break;
+
+                                                case OP_WHITESPACE:
+                                                        for (i = 1; i <= min; i++)
+                                                                if ((md->ctypes[*eptr++] & ctype_space) == 0)
+                                                                        return FALSE;
+                                                        break;
+
+                                                case OP_NOT_WORDCHAR:
+                                                        for (i = 1; i <= min; i++)
+                                                                if ((md->ctypes[*eptr++] & ctype_word) != 0)
+                                                                        return FALSE;
+                                                        break;
+
+                                                case OP_WORDCHAR:
+                                                        for (i = 1; i <= min; i++)
+                                                                if ((md->ctypes[*eptr++] & ctype_word) == 0)
+                                                                        return FALSE;
+                                                        break;
+                                        }
+
+                                if (min == max)
+                                        continue;
+
+                                if (minimize) {
+                                        for (i = min;; i++) {
+                                                if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+                                                        return TRUE;
+                                                if (i >= max || eptr >= md->end_subject)
+                                                        return FALSE;
+
+                                                c = *eptr++;
+                                                switch (ctype) {
+                                                        case OP_ANY:
+                                                                if ((ims & PCRE_DOTALL) == 0 && c == '\n')
+                                                                        return FALSE;
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-          if (md->utf8)
-            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+                                                                if (md->utf8)
+                                                                        while (eptr < md->end_subject
+                                                                                   && (*eptr & 0xc0) == 0x80)
+                                                                                eptr++;
 #endif
-          break;
-
-          case OP_NOT_DIGIT:
-          if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
-          break;
-
-          case OP_DIGIT:
-          if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
-          break;
-
-          case OP_NOT_WHITESPACE:
-          if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
-          break;
-
-          case OP_WHITESPACE:
-          if  ((md->ctypes[c] & ctype_space) == 0) return FALSE;
-          break;
-
-          case OP_NOT_WORDCHAR:
-          if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
-          break;
-
-          case OP_WORDCHAR:
-          if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
-          break;
-          }
-        }
-      /* 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). */
-
-    else
-      {
-      const uschar *pp = eptr;
-      switch(ctype)
-        {
-        case OP_ANY:
+                                                                break;
 
-        /* Special code is required for UTF8, but when the maximum is unlimited
-        we don't need it. */
+                                                        case OP_NOT_DIGIT:
+                                                                if ((md->ctypes[c] & ctype_digit) != 0)
+                                                                        return FALSE;
+                                                                break;
+
+                                                        case OP_DIGIT:
+                                                                if ((md->ctypes[c] & ctype_digit) == 0)
+                                                                        return FALSE;
+                                                                break;
+
+                                                        case OP_NOT_WHITESPACE:
+                                                                if ((md->ctypes[c] & ctype_space) != 0)
+                                                                        return FALSE;
+                                                                break;
+
+                                                        case OP_WHITESPACE:
+                                                                if ((md->ctypes[c] & ctype_space) == 0)
+                                                                        return FALSE;
+                                                                break;
+
+                                                        case OP_NOT_WORDCHAR:
+                                                                if ((md->ctypes[c] & ctype_word) != 0)
+                                                                        return FALSE;
+                                                                break;
+
+                                                        case OP_WORDCHAR:
+                                                                if ((md->ctypes[c] & ctype_word) == 0)
+                                                                        return FALSE;
+                                                                break;
+                                                }
+                                        }
+                                }
+
+                                else {
+                                        const uschar *pp = eptr;
+                                        switch (ctype) {
+                                                case OP_ANY:
 
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-        if (md->utf8 && max < INT_MAX)
-          {
-          if ((ims & PCRE_DOTALL) == 0)
-            {
-            for (i = min; i < max; i++)
-              {
-              if (eptr >= md->end_subject || *eptr++ == '\n') break;
-              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
-              }
-            }
-          else
-            {
-            for (i = min; i < max; i++)
-              {
-              eptr++;
-              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
-              }
-            }
-          break;
-          }
+                                                        if (md->utf8 && max < INT_MAX) {
+                                                                if ((ims & PCRE_DOTALL) == 0) {
+                                                                        for (i = min; i < max; i++) {
+                                                                                if (eptr >= md->end_subject
+                                                                                        || *eptr++ == '\n')
+                                                                                        break;
+                                                                                while (eptr < md->end_subject
+                                                                                           && (*eptr & 0xc0) == 0x80)
+                                                                                        eptr++;
+                                                                        }
+                                                                }
+                                                                else {
+                                                                        for (i = min; i < max; i++) {
+                                                                                eptr++;
+                                                                                while (eptr < md->end_subject
+                                                                                           && (*eptr & 0xc0) == 0x80)
+                                                                                        eptr++;
+                                                                        }
+                                                                }
+                                                                break;
+                                                        }
 #endif
-        /* Non-UTF8 can be faster */
-        if ((ims & PCRE_DOTALL) == 0)
-          {
-          for (i = min; i < max; i++)
-            {
-            if (eptr >= md->end_subject || *eptr == '\n') break;
-            eptr++;
-            }
-          }
-        else
-          {
-          c = max - min;
-          if (c > md->end_subject - eptr) c = md->end_subject - eptr;
-          eptr += c;
-          }
-        break;
-
-        case OP_NOT_DIGIT:
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
-            break;
-          eptr++;
-          }
-        break;
-
-        case OP_DIGIT:
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
-            break;
-          eptr++;
-          }
-        break;
-
-        case OP_NOT_WHITESPACE:
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
-            break;
-          eptr++;
-          }
-        break;
-
-        case OP_WHITESPACE:
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
-            break;
-          eptr++;
-          }
-        break;
-
-        case OP_NOT_WORDCHAR:
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
-            break;
-          eptr++;
-          }
-        break;
-
-        case OP_WORDCHAR:
-        for (i = min; i < max; i++)
-          {
-          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
-            break;
-          eptr++;
-          }
-        break;
-        }
-
-      while (eptr >= pp)
-        {
-        if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
-          return TRUE;
+                                                        if ((ims & PCRE_DOTALL) == 0) {
+                                                                for (i = min; i < max; i++) {
+                                                                        if (eptr >= md->end_subject
+                                                                                || *eptr == '\n') break;
+                                                                        eptr++;
+                                                                }
+                                                        }
+                                                        else {
+                                                                c = max - min;
+                                                                if (c > md->end_subject - eptr)
+                                                                        c = md->end_subject - eptr;
+                                                                eptr += c;
+                                                        }
+                                                        break;
+
+                                                case OP_NOT_DIGIT:
+                                                        for (i = min; i < max; i++) {
+                                                                if (eptr >= md->end_subject
+                                                                        || (md->ctypes[*eptr] & ctype_digit) != 0)
+                                                                        break;
+                                                                eptr++;
+                                                        }
+                                                        break;
+
+                                                case OP_DIGIT:
+                                                        for (i = min; i < max; i++) {
+                                                                if (eptr >= md->end_subject
+                                                                        || (md->ctypes[*eptr] & ctype_digit) == 0)
+                                                                        break;
+                                                                eptr++;
+                                                        }
+                                                        break;
+
+                                                case OP_NOT_WHITESPACE:
+                                                        for (i = min; i < max; i++) {
+                                                                if (eptr >= md->end_subject
+                                                                        || (md->ctypes[*eptr] & ctype_space) != 0)
+                                                                        break;
+                                                                eptr++;
+                                                        }
+                                                        break;
+
+                                                case OP_WHITESPACE:
+                                                        for (i = min; i < max; i++) {
+                                                                if (eptr >= md->end_subject
+                                                                        || (md->ctypes[*eptr] & ctype_space) == 0)
+                                                                        break;
+                                                                eptr++;
+                                                        }
+                                                        break;
+
+                                                case OP_NOT_WORDCHAR:
+                                                        for (i = min; i < max; i++) {
+                                                                if (eptr >= md->end_subject
+                                                                        || (md->ctypes[*eptr] & ctype_word) != 0)
+                                                                        break;
+                                                                eptr++;
+                                                        }
+                                                        break;
+
+                                                case OP_WORDCHAR:
+                                                        for (i = min; i < max; i++) {
+                                                                if (eptr >= md->end_subject
+                                                                        || (md->ctypes[*eptr] & ctype_word) == 0)
+                                                                        break;
+                                                                eptr++;
+                                                        }
+                                                        break;
+                                        }
+
+                                        while (eptr >= pp) {
+                                                if (match
+                                                        (eptr--, ecode, offset_top, md, ims, eptrb,
+                                                         0)) return TRUE;
 #ifdef L2_UT_PCRE_SUPPORT_UTF8
-        if (md->utf8)
-          while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
+                                                if (md->utf8)
+                                                        while (eptr > pp && (*eptr & 0xc0) == 0x80)
+                                                                eptr--;
 #endif
-        }
-      return FALSE;
-      }
-    /* Control never gets here */
+                                        }
+                                        return FALSE;
+                                }
 
-    /* There's been some horrible disaster. */
+                        default:
 
-    default:
+                                md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
+                                return FALSE;
+                }
 
-    md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
-    return FALSE;
-    }
-
-  /* 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. */
-
-  }
-/* Control never reaches here */
+        }
 }
 
-/*************************************************
-*         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:
-  external_re     points to the compiled expression
-  external_extra  points to "hints" from pcre_study() 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
-*/
-
 int
-pcre_exec(const pcre *external_re, const pcre_extra *external_extra,
-  const char *subject, int length, int start_offset, int options, int *offsets,
-  int offsetcount)
+pcre_exec(const pcre * external_re, const pcre_extra * external_extra,
+                  const char *subject, int length, int start_offset, int options,
+                  int *offsets, int offsetcount)
 {
-int resetcount, ocount;
-int first_char = -1;
-int req_char = -1;
-int req_char2 = -1;
-unsigned long int ims = 0;
-match_data match_block;
-const uschar *start_bits = NULL;
-const uschar *start_match = (const uschar *)subject + start_offset;
-const uschar *end_subject;
-const uschar *req_char_ptr = start_match - 1;
-const real_pcre *re = (const real_pcre *)external_re;
-const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
-BOOL using_temporary_offsets = FALSE;
-BOOL anchored;
-BOOL startline;
-
-if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
-
-if (re == NULL || subject == NULL ||
-   (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
-if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
-
-anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
-startline = (re->options & PCRE_STARTLINE) != 0;
-
-match_block.start_pattern = re->code;
-match_block.start_subject = (const uschar *)subject;
-match_block.end_subject = match_block.start_subject + length;
-end_subject = match_block.end_subject;
-
-match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
-match_block.utf8 = (re->options & PCRE_UTF8) != 0;
-
-match_block.notbol = (options & PCRE_NOTBOL) != 0;
-match_block.noteol = (options & PCRE_NOTEOL) != 0;
-match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
-
-match_block.errorcode = PCRE_ERROR_NOMATCH;     /* Default error */
-
-match_block.lcc = re->tables + lcc_offset;
-match_block.ctypes = re->tables + ctypes_offset;
-
-/* 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 bit 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;
-  match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
-  if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
-  using_temporary_offsets = TRUE;
-
-  }
-else match_block.offset_vector = offsets;
-
-match_block.offset_end = ocount;
-match_block.offset_max = (2*ocount)/3;
-match_block.offset_overflow = FALSE;
-
-/* 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 (match_block.offset_vector != NULL)
-  {
-  register int *iptr = match_block.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_char value is
-never set for an anchored regular expression, but the anchoring may be forced
-at run time, so we have to test for anchoring. The first char may be unset for
-an unanchored pattern, of course. If there's no first char and the pattern was
-studied, there may be a bitmap of possible first characters. */
-
-if (!anchored)
-  {
-  if ((re->options & PCRE_FIRSTSET) != 0)
-    {
-    first_char = re->first_char;
-    if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
-    }
-  else
-    if (!startline && extra != NULL &&
-      (extra->options & PCRE_STUDY_MAPPED) != 0)
-        start_bits = extra->start_bits;
-  }
-
-/* For anchored or unanchored matches, there may be a "last known required
-character" set. If the PCRE_CASELESS is set, implying that the match starts
-caselessly, or if there are any changes of this flag within the regex, set up
-both cases of the character. Otherwise set the two values the same, which will
-avoid duplicate testing (which takes significant time). This covers the vast
-majority of cases. It will be suboptimal when the case flag changes in a regex
-and the required character in fact is caseful. */
-
-if ((re->options & PCRE_REQCHSET) != 0)
-  {
-  req_char = re->req_char;
-  req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)?
-    (re->tables + fcc_offset)[req_char] : req_char;
-  }
-
-/* Loop for handling unanchored repeated matching attempts; for anchored regexs
-the loop runs just once. */
-
-do
-  {
-  int rc;
-  register int *iptr = match_block.offset_vector;
-  register int *iend = iptr + resetcount;
-
-  /* Reset the maximum number of extractions we might see. */
-
-  while (iptr < iend) *iptr++ = -1;
-
-  /* Advance to a unique first char if possible */
-
-  if (first_char >= 0)
-    {
-    if ((ims & PCRE_CASELESS) != 0)
-      while (start_match < end_subject &&
-             match_block.lcc[*start_match] != first_char)
-        start_match++;
-    else
-      while (start_match < end_subject && *start_match != first_char)
-        start_match++;
-    }
-
-  /* Or to just after \n for a multiline match if possible */
-
-  else if (startline)
-    {
-    if (start_match > match_block.start_subject + start_offset)
-      {
-      while (start_match < end_subject && start_match[-1] != '\n')
-        start_match++;
-      }
-    }
-
-  /* Or to a non-unique first char after study */
-
-  else if (start_bits != NULL)
-    {
-    while (start_match < end_subject)
-      {
-      register int c = *start_match;
-      if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
-      }
-    }
+        int resetcount, ocount;
+        int first_char = -1;
+        int req_char = -1;
+        int req_char2 = -1;
+        unsigned long int ims = 0;
+        match_data match_block;
+        const uschar *start_bits = NULL;
+        const uschar *start_match = (const uschar *)subject + start_offset;
+        const uschar *end_subject;
+        const uschar *req_char_ptr = start_match - 1;
+        const real_pcre *re = (const real_pcre *)external_re;
+        const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
+        BOOL using_temporary_offsets = FALSE;
+        BOOL anchored;
+        BOOL startline;
+
+        if ((options & ~PUBLIC_EXEC_OPTIONS) != 0)
+                return PCRE_ERROR_BADOPTION;
+
+        if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0))
+                return PCRE_ERROR_NULL;
+        if (re->magic_number != MAGIC_NUMBER)
+                return PCRE_ERROR_BADMAGIC;
+
+        anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
+        startline = (re->options & PCRE_STARTLINE) != 0;
+
+        match_block.start_pattern = re->code;
+        match_block.start_subject = (const uschar *)subject;
+        match_block.end_subject = match_block.start_subject + length;
+        end_subject = match_block.end_subject;
+
+        match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+        match_block.utf8 = (re->options & PCRE_UTF8) != 0;
+
+        match_block.notbol = (options & PCRE_NOTBOL) != 0;
+        match_block.noteol = (options & PCRE_NOTEOL) != 0;
+        match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
+
+        match_block.errorcode = PCRE_ERROR_NOMATCH;
+
+        match_block.lcc = re->tables + lcc_offset;
+        match_block.ctypes = re->tables + ctypes_offset;
+
+        ims = re->options & (PCRE_CASELESS | PCRE_MULTILINE | PCRE_DOTALL);
+
+        ocount = offsetcount - (offsetcount % 3);
+
+        if (re->top_backref > 0 && re->top_backref >= ocount / 3) {
+                ocount = re->top_backref * 3 + 3;
+                match_block.offset_vector =
+                        (int *)(pcre_malloc) (ocount * sizeof (int));
+                if (match_block.offset_vector == NULL)
+                        return PCRE_ERROR_NOMEMORY;
+                using_temporary_offsets = TRUE;
+
+        }
+        else
+                match_block.offset_vector = offsets;
+
+        match_block.offset_end = ocount;
+        match_block.offset_max = (2 * ocount) / 3;
+        match_block.offset_overflow = FALSE;
+
+        resetcount = 2 + re->top_bracket * 2;
+        if (resetcount > offsetcount)
+                resetcount = ocount;
+
+        if (match_block.offset_vector != NULL) {
+                register int *iptr = match_block.offset_vector + ocount;
+                register int *iend = iptr - resetcount / 2 + 1;
+                while (--iptr >= iend)
+                        *iptr = -1;
+        }
+
+        if (!anchored) {
+                if ((re->options & PCRE_FIRSTSET) != 0) {
+                        first_char = re->first_char;
+                        if ((ims & PCRE_CASELESS) != 0)
+                                first_char = match_block.lcc[first_char];
+                }
+                else
+                        if (!startline && extra != NULL &&
+                                (extra->options & PCRE_STUDY_MAPPED) != 0)
+                        start_bits = extra->start_bits;
+        }
+
+        if ((re->options & PCRE_REQCHSET) != 0) {
+                req_char = re->req_char;
+                req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0) ?
+                        (re->tables + fcc_offset)[req_char] : req_char;
+        }
+
+        do {
+                int rc;
+                register int *iptr = match_block.offset_vector;
+                register int *iend = iptr + resetcount;
+
+                while (iptr < iend)
+                        *iptr++ = -1;
+
+                if (first_char >= 0) {
+                        if ((ims & PCRE_CASELESS) != 0)
+                                while (start_match < end_subject &&
+                                           match_block.lcc[*start_match] != first_char)
+                                        start_match++;
+                        else
+                                while (start_match < end_subject
+                                           && *start_match != first_char) start_match++;
+                }
+
+                else if (startline) {
+                        if (start_match > match_block.start_subject + start_offset) {
+                                while (start_match < end_subject && start_match[-1] != '\n')
+                                        start_match++;
+                        }
+                }
+
+                else if (start_bits != NULL) {
+                        while (start_match < end_subject) {
+                                register int c = *start_match;
+                                if ((start_bits[c / 8] & (1 << (c & 7))) == 0)
+                                        start_match++;
+                                else
+                                        break;
+                        }
+                }
+
+                if (req_char >= 0) {
+                        register const uschar *p =
+                                start_match + ((first_char >= 0) ? 1 : 0);
+
+                        if (p > req_char_ptr) {
+                                if (req_char == req_char2) {
+                                        while (p < end_subject) {
+                                                if (*p++ == req_char) {
+                                                        p--;
+                                                        break;
+                                                }
+                                        }
+                                }
+
+                                else {
+                                        while (p < end_subject) {
+                                                register int pp = *p++;
+                                                if (pp == req_char || pp == req_char2) {
+                                                        p--;
+                                                        break;
+                                                }
+                                        }
+                                }
+
+                                if (p >= end_subject)
+                                        break;
+
+                                req_char_ptr = p;
+                        }
+                }
+
+                match_block.start_match = start_match;
+                if (!match
+                        (start_match, re->code, 2, &match_block, ims, NULL,
+                         match_isgroup)) continue;
+
+                if (using_temporary_offsets) {
+                        if (offsetcount >= 4) {
+                                memcpy(offsets + 2, match_block.offset_vector + 2,
+                                           (offsetcount - 2) * sizeof (int));
+
+                        }
+                        if (match_block.end_offset_top > offsetcount)
+                                match_block.offset_overflow = TRUE;
+
+                        (pcre_free) (match_block.offset_vector);
+                }
+
+                rc = match_block.offset_overflow ? 0 : match_block.end_offset_top / 2;
+
+                if (match_block.offset_end < 2)
+                        rc = 0;
+                else {
+                        offsets[0] = start_match - match_block.start_subject;
+                        offsets[1] =
+                                match_block.end_match_ptr - match_block.start_subject;
+                }
+
+                return rc;
+        }
+
+        while (!anchored &&
+                   match_block.errorcode == PCRE_ERROR_NOMATCH &&
+                   start_match++ < end_subject);
 
-  /* If req_char is set, we know that that character must appear in the subject
-  for the match to succeed. If the first character is set, req_char must be
-  later in the subject; otherwise the test starts at the match point. This
-  optimization can save a huge amount of backtracking in patterns with nested
-  unlimited repeats that aren't going to match. We don't know what the state of
-  case matching may be when this character is hit, so test for it in both its
-  cases if necessary. However, the different cased versions will not be set up
-  unless PCRE_CASELESS was given or the casing state changes within the regex.
-  Writing separate code makes it go faster, as does using an autoincrement and
-  backing off on a match. */
-
-  if (req_char >= 0)
-    {
-    register const uschar *p = start_match + ((first_char >= 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_char_ptr)
-      {
-      /* Do a single test if no case difference is set up */
-
-      if (req_char == req_char2)
-        {
-        while (p < end_subject)
-          {
-          if (*p++ == req_char) { p--; break; }
-          }
-        }
-
-      /* Otherwise test for either case */
-
-      else
-        {
-        while (p < end_subject)
-          {
-          register int pp = *p++;
-          if (pp == req_char || pp == req_char2) { p--; break; }
-          }
-        }
-
-      /* If we can't find the required character, break the matching loop */
-
-      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. */
+        if (using_temporary_offsets) {
 
-      req_char_ptr = p;
-      }
-    }
-
-  /* When a match occurs, substrings will be set for all internal extractions;
-  we just need to set up the whole thing as substring 0 before returning. If
-  there were too many extractions, set the return code to zero. In the case
-  where we had to get some local store to hold offsets for backreferences, copy
-  those back references that we can. In this case there need not be overflow
-  if certain parts of the pattern were not used. */
-
-  match_block.start_match = start_match;
-  if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
-    continue;
-
-  /* Copy the offset information from temporary store if necessary */
-
-  if (using_temporary_offsets)
-    {
-    if (offsetcount >= 4)
-      {
-      memcpy(offsets + 2, match_block.offset_vector + 2,
-        (offsetcount - 2) * sizeof(int));
-
-      }
-    if (match_block.end_offset_top > offsetcount)
-      match_block.offset_overflow = TRUE;
-
-    (pcre_free)(match_block.offset_vector);
-    }
-
-  rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
-
-  if (match_block.offset_end < 2) rc = 0; else
-    {
-    offsets[0] = start_match - match_block.start_subject;
-    offsets[1] = match_block.end_match_ptr - match_block.start_subject;
-    }
+                (pcre_free) (match_block.offset_vector);
+        }
 
-  return rc;
-  }
-
-/* This "while" is the end of the "do" above */
-
-while (!anchored &&
-       match_block.errorcode == PCRE_ERROR_NOMATCH &&
-       start_match++ < end_subject);
-
-if (using_temporary_offsets)
-  {
-
-  (pcre_free)(match_block.offset_vector);
-  }
-
-return match_block.errorcode;
+        return match_block.errorcode;
 }
 
-/* ____ END pcre.c ____ */
-
-/* ____ BEGIN study.c ____ */
-
-/* Include the internals header, which itself includes Standard C headers plus
-the external pcre header. */
-
-/*************************************************
-*      Set a bit and maybe its alternate case    *
-*************************************************/
-
-/* Given a character, set its bit in the table, and also the bit for the other
-version of a letter if we are caseless.
-
-Arguments:
-  start_bits    points to the bit map
-  c             is the character
-  caseless      the caseless flag
-  cd            the block with char table pointers
-
-Returns:        nothing
-*/
-
 static void
-set_bit(uschar *start_bits, int c, BOOL caseless, compile_data *cd)
+set_bit(uschar * start_bits, int c, BOOL caseless, compile_data * cd)
 {
-start_bits[c/8] |= (1 << (c&7));
-if (caseless && (cd->ctypes[c] & ctype_letter) != 0)
-  start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7));
+        start_bits[c / 8] |= (1 << (c & 7));
+        if (caseless && (cd->ctypes[c] & ctype_letter) != 0)
+                start_bits[cd->fcc[c] / 8] |= (1 << (cd->fcc[c] & 7));
 }
 
-/*************************************************
-*          Create bitmap of starting chars       *
-*************************************************/
-
-/* This function scans a compiled unanchored expression and attempts to build a
-bitmap of the set of initial characters. If it can't, it returns FALSE. As time
-goes by, we may be able to get more clever at doing this.
-
-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
-  cd           the block with char table pointers
-
-Returns:       TRUE if table built, FALSE otherwise
-*/
-
 static BOOL
-set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless,
-  compile_data *cd)
+set_start_bits(const uschar * code, uschar * start_bits, BOOL caseless,
+                           compile_data * cd)
 {
-register int c;
+        register int c;
 
-/* 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;
-
-do
-  {
-  const uschar *tcode = code + 3;
-  BOOL try_next = TRUE;
-
-  while (try_next)
-    {
-    /* If a branch starts with a bracket or a positive lookahead assertion,
-    recurse to set bits from within them. That's all for this branch. */
-
-    if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT)
-      {
-      if (!set_start_bits(tcode, start_bits, caseless, cd))
-        return FALSE;
-      try_next = FALSE;
-      }
-
-    else switch(*tcode)
-      {
-      default:
-      return FALSE;
-
-      /* Skip over extended extraction bracket number */
-
-      case OP_BRANUMBER:
-      tcode += 3;
-      break;
-
-      /* Skip over lookbehind and negative lookahead assertions */
-
-      case OP_ASSERT_NOT:
-      case OP_ASSERTBACK:
-      case OP_ASSERTBACK_NOT:
-      do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT);
-      tcode += 3;
-      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, cd))
-        return FALSE;
-      dummy = 1;
-      do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT);
-      tcode += 3;
-      break;
-
-      /* Single-char * or ? sets the bit and tries the next item */
-
-      case OP_STAR:
-      case OP_MINSTAR:
-      case OP_QUERY:
-      case OP_MINQUERY:
-      set_bit(start_bits, tcode[1], caseless, cd);
-      tcode += 2;
-      break;
-
-      /* Single-char upto sets the bit and tries the next */
-
-      case OP_UPTO:
-      case OP_MINUPTO:
-      set_bit(start_bits, tcode[3], caseless, cd);
-      tcode += 4;
-      break;
-
-      /* At least one single char sets the bit and stops */
-
-      case OP_EXACT:       /* Fall through */
-      tcode++;
-
-      case OP_CHARS:       /* Fall through */
-      tcode++;
-
-      case OP_PLUS:
-      case OP_MINPLUS:
-      set_bit(start_bits, tcode[1], caseless, cd);
-      try_next = FALSE;
-      break;
-
-      /* Single character type sets the bits and stops */
-
-      case OP_NOT_DIGIT:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= ~cd->cbits[c+cbit_digit];
-      try_next = FALSE;
-      break;
-
-      case OP_DIGIT:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= cd->cbits[c+cbit_digit];
-      try_next = FALSE;
-      break;
-
-      case OP_NOT_WHITESPACE:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= ~cd->cbits[c+cbit_space];
-      try_next = FALSE;
-      break;
-
-      case OP_WHITESPACE:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= cd->cbits[c+cbit_space];
-      try_next = FALSE;
-      break;
-
-      case OP_NOT_WORDCHAR:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= ~cd->cbits[c+cbit_word];
-      try_next = FALSE;
-      break;
-
-      case OP_WORDCHAR:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= cd->cbits[c+cbit_word];
-      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:
-      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:
-      tcode += 2;               /* Fall through */
-
-      case OP_TYPESTAR:
-      case OP_TYPEMINSTAR:
-      case OP_TYPEQUERY:
-      case OP_TYPEMINQUERY:
-      switch(tcode[1])
-        {
-        case OP_NOT_DIGIT:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= ~cd->cbits[c+cbit_digit];
-        break;
-
-        case OP_DIGIT:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= cd->cbits[c+cbit_digit];
-        break;
-
-        case OP_NOT_WHITESPACE:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= ~cd->cbits[c+cbit_space];
-        break;
-
-        case OP_WHITESPACE:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= cd->cbits[c+cbit_space];
-        break;
-
-        case OP_NOT_WORDCHAR:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= ~cd->cbits[c+cbit_word];
-        break;
-
-        case OP_WORDCHAR:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= cd->cbits[c+cbit_word];
-        break;
-        }
-
-      tcode += 2;
-      break;
-
-      /* Character class: set the bits and either carry on or not,
-      according to the repeat count. */
-
-      case OP_CLASS:
-        {
-        tcode++;
-        for (c = 0; c < 32; c++) start_bits[c] |= tcode[c];
-        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;
-
-      }
-    }
+        volatile int dummy;
 
-  code += (code[1] << 8) + code[2];   /* Advance to next branch */
-  }
-while (*code == OP_ALT);
-return TRUE;
+        do {
+                const uschar *tcode = code + 3;
+                BOOL try_next = TRUE;
+
+                while (try_next) {
+                        if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT) {
+                                if (!set_start_bits(tcode, start_bits, caseless, cd))
+                                        return FALSE;
+                                try_next = FALSE;
+                        }
+
+                        else
+                                switch (*tcode) {
+                                        default:
+                                                return FALSE;
+
+                                        case OP_BRANUMBER:
+                                                tcode += 3;
+                                                break;
+
+                                        case OP_ASSERT_NOT:
+                                        case OP_ASSERTBACK:
+                                        case OP_ASSERTBACK_NOT:
+                                                do
+                                                        tcode += (tcode[1] << 8) + tcode[2];
+                                                while (*tcode == OP_ALT);
+                                                tcode += 3;
+                                                break;
+
+                                        case OP_OPT:
+                                                caseless = (tcode[1] & PCRE_CASELESS) != 0;
+                                                tcode += 2;
+                                                break;
+
+                                        case OP_BRAZERO:
+                                        case OP_BRAMINZERO:
+                                                if (!set_start_bits
+                                                        (++tcode, start_bits, caseless, cd)) return FALSE;
+                                                dummy = 1;
+                                                do
+                                                        tcode += (tcode[1] << 8) + tcode[2];
+                                                while (*tcode == OP_ALT);
+                                                tcode += 3;
+                                                break;
+
+                                        case OP_STAR:
+                                        case OP_MINSTAR:
+                                        case OP_QUERY:
+                                        case OP_MINQUERY:
+                                                set_bit(start_bits, tcode[1], caseless, cd);
+                                                tcode += 2;
+                                                break;
+
+                                        case OP_UPTO:
+                                        case OP_MINUPTO:
+                                                set_bit(start_bits, tcode[3], caseless, cd);
+                                                tcode += 4;
+                                                break;
+
+                                        case OP_EXACT:
+                                                tcode++;
+
+                                        case OP_CHARS:
+                                                tcode++;
+
+                                        case OP_PLUS:
+                                        case OP_MINPLUS:
+                                                set_bit(start_bits, tcode[1], caseless, cd);
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_NOT_DIGIT:
+                                                for (c = 0; c < 32; c++)
+                                                        start_bits[c] |= ~cd->cbits[c + cbit_digit];
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_DIGIT:
+                                                for (c = 0; c < 32; c++)
+                                                        start_bits[c] |= cd->cbits[c + cbit_digit];
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_NOT_WHITESPACE:
+                                                for (c = 0; c < 32; c++)
+                                                        start_bits[c] |= ~cd->cbits[c + cbit_space];
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_WHITESPACE:
+                                                for (c = 0; c < 32; c++)
+                                                        start_bits[c] |= cd->cbits[c + cbit_space];
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_NOT_WORDCHAR:
+                                                for (c = 0; c < 32; c++)
+                                                        start_bits[c] |= ~cd->cbits[c + cbit_word];
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_WORDCHAR:
+                                                for (c = 0; c < 32; c++)
+                                                        start_bits[c] |= cd->cbits[c + cbit_word];
+                                                try_next = FALSE;
+                                                break;
+
+                                        case OP_TYPEPLUS:
+                                        case OP_TYPEMINPLUS:
+                                                tcode++;
+                                                break;
+
+                                        case OP_TYPEEXACT:
+                                                tcode += 3;
+                                                break;
+
+                                        case OP_TYPEUPTO:
+                                        case OP_TYPEMINUPTO:
+                                                tcode += 2;
+
+                                        case OP_TYPESTAR:
+                                        case OP_TYPEMINSTAR:
+                                        case OP_TYPEQUERY:
+                                        case OP_TYPEMINQUERY:
+                                                switch (tcode[1]) {
+                                                        case OP_NOT_DIGIT:
+                                                                for (c = 0; c < 32; c++)
+                                                                        start_bits[c] |=
+                                                                                ~cd->cbits[c + cbit_digit];
+                                                                break;
+
+                                                        case OP_DIGIT:
+                                                                for (c = 0; c < 32; c++)
+                                                                        start_bits[c] |=
+                                                                                cd->cbits[c + cbit_digit];
+                                                                break;
+
+                                                        case OP_NOT_WHITESPACE:
+                                                                for (c = 0; c < 32; c++)
+                                                                        start_bits[c] |=
+                                                                                ~cd->cbits[c + cbit_space];
+                                                                break;
+
+                                                        case OP_WHITESPACE:
+                                                                for (c = 0; c < 32; c++)
+                                                                        start_bits[c] |=
+                                                                                cd->cbits[c + cbit_space];
+                                                                break;
+
+                                                        case OP_NOT_WORDCHAR:
+                                                                for (c = 0; c < 32; c++)
+                                                                        start_bits[c] |=
+                                                                                ~cd->cbits[c + cbit_word];
+                                                                break;
+
+                                                        case OP_WORDCHAR:
+                                                                for (c = 0; c < 32; c++)
+                                                                        start_bits[c] |= cd->cbits[c + cbit_word];
+                                                                break;
+                                                }
+
+                                                tcode += 2;
+                                                break;
+
+                                        case OP_CLASS:
+                                                {
+                                                        tcode++;
+                                                        for (c = 0; c < 32; c++)
+                                                                start_bits[c] |= tcode[c];
+                                                        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;
+
+                                }
+                }
+
+                code += (code[1] << 8) + code[2];
+        }
+        while (*code == OP_ALT);
+        return TRUE;
 }
 
-/*************************************************
-*          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,
-            NULL on error or if no optimization possible
-*/
-
-pcre_extra *
-pcre_study(const pcre *external_re, int options, const char **errorptr)
+pcre_extra *pcre_study(const pcre * external_re, int options,
+                                           const char **errorptr)
 {
-uschar start_bits[32];
-real_pcre_extra *extra;
-const real_pcre *re = (const real_pcre *)external_re;
-compile_data compile_block;
-
-*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;
-  }
-
-/* For an anchored pattern, or an unchored pattern that has a first char, or a
-multiline pattern that matches only at "line starts", no further processing at
-present. */
-
-if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0)
-  return NULL;
-
-/* Set the character tables in the block which is passed around */
-
-compile_block.lcc = re->tables + lcc_offset;
-compile_block.fcc = re->tables + fcc_offset;
-compile_block.cbits = re->tables + cbits_offset;
-compile_block.ctypes = re->tables + ctypes_offset;
+        uschar start_bits[32];
+        real_pcre_extra *extra;
+        const real_pcre *re = (const real_pcre *)external_re;
+        compile_data compile_block;
+
+        *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;
+        }
+
+        if ((re->options & (PCRE_ANCHORED | PCRE_FIRSTSET | PCRE_STARTLINE)) != 0)
+                return NULL;
+
+        compile_block.lcc = re->tables + lcc_offset;
+        compile_block.fcc = re->tables + fcc_offset;
+        compile_block.cbits = re->tables + cbits_offset;
+        compile_block.ctypes = re->tables + ctypes_offset;
+
+        memset(start_bits, 0, 32 * sizeof (uschar));
+        if (!set_start_bits
+                (re->code, start_bits, (re->options & PCRE_CASELESS) != 0,
+                 &compile_block)) return NULL;
+
+        extra = (real_pcre_extra *) (pcre_malloc) (sizeof (real_pcre_extra));
+
+        if (extra == NULL) {
+                *errorptr = "failed to get memory";
+                return NULL;
+        }
 
-/* See if we can find a fixed set of initial characters for the pattern. */
+        extra->options = PCRE_STUDY_MAPPED;
+        memcpy(extra->start_bits, start_bits, sizeof (start_bits));
 
-memset(start_bits, 0, 32 * sizeof(uschar));
-if (!set_start_bits(re->code, start_bits, (re->options & PCRE_CASELESS) != 0,
-  &compile_block)) return NULL;
-
-/* Get an "extra" block and put the information therein. */
-
-extra = (real_pcre_extra *)(pcre_malloc)(sizeof(real_pcre_extra));
-
-if (extra == NULL)
-  {
-  *errorptr = "failed to get memory";
-  return NULL;
-  }
-
-extra->options = PCRE_STUDY_MAPPED;
-memcpy(extra->start_bits, start_bits, sizeof(start_bits));
-
-return (pcre_extra *)extra;
+        return (pcre_extra *) extra;
 }
 
-/* ____ END study.c ____ */
-
-/* ____ BEGIN get.c ____ */
-
-/* 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 <scottw@cgibuilder.com>. */
-
-/* Include the internals header, which itself includes Standard C headers plus
-the external pcre header. */
-
-/*************************************************
-*      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
-*/
-
 int
 pcre_copy_substring(const char *subject, int *ovector, int stringcount,
-  int stringnumber, char *buffer, int size)
+                                        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;
+        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 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
-*/
-
 int
 pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
-  const char ***listptr)
+                                                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;
-  }
+        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;
+        *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
-*/
-
-void
-pcre_free_substring_list(const char **pointer)
+void pcre_free_substring_list(const char **pointer)
 {
-(pcre_free)((void *)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
-*/
-
 int
 pcre_get_substring(const char *subject, int *ovector, int stringcount,
-  int stringnumber, const char **stringptr)
+                                   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;
+        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;
 }
 
-/*************************************************
-*       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
-*/
-
-void
-pcre_free_substring(const char *pointer)
+void pcre_free_substring(const char *pointer)
 {
-(pcre_free)((void *)pointer);
+        (pcre_free) ((void *)pointer);
 }
 
-/* ____ END get.c ____ */
-
-#endif /* !L2_UT_PCRE_GENTAB */
-
-/* ____ BEGIN maketables.c ____ */
-
-/* This 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. */
-
-/*************************************************
-*           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
-*/
+#endif
 
-const unsigned char *
-pcre_maketables(void)
+const unsigned char *pcre_maketables(void)
 {
-unsigned char *yield, *p;
-int i;
+        unsigned char *yield, *p;
+        int i;
 
-#ifndef L2_UT_PCRE_GENTAB
-yield = (unsigned char*)(pcre_malloc)(tables_length);
+#ifndef L2_UT_PCRE_TAB
+        yield = (unsigned char *)(pcre_malloc) (tables_length);
 #else
-yield = (unsigned char*)malloc(tables_length);
+        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 */
+        if (yield == NULL)
+                return NULL;
+        p = yield;
+
+        for (i = 0; i < 256; i++)
+                *p++ = tolower(i);
+
+        for (i = 0; i < 256; i++)
+                *p++ = islower(i) ? toupper(i) : tolower(i);
+
+        memset(p, 0, cbit_length);
+        for (i = 0; i < 256; i++) {
+                if (isdigit(i)) {
+                        p[cbit_digit + i / 8] |= 1 << (i & 7);
+                        p[cbit_word + i / 8] |= 1 << (i & 7);
+                }
+                if (isupper(i)) {
+                        p[cbit_upper + i / 8] |= 1 << (i & 7);
+                        p[cbit_word + i / 8] |= 1 << (i & 7);
+                }
+                if (islower(i)) {
+                        p[cbit_lower + i / 8] |= 1 << (i & 7);
+                        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;
+
+        for (i = 0; i < 256; i++) {
+                int x = 0;
+                if (isspace(i))
+                        x += ctype_space;
+                if (isalpha(i))
+                        x += ctype_letter;
+                if (isdigit(i))
+                        x += ctype_digit;
+                if (isxdigit(i))
+                        x += ctype_xdigit;
+                if (isalnum(i) || i == '_')
+                        x += ctype_word;
+                if (strchr("*+?{^.$|()[", i) != 0)
+                        x += ctype_meta;
+                *p++ = x;
+        }
 
-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. */
-
-memset(p, 0, cbit_length);
-for (i = 0; i < 256; i++)
-  {
-  if (isdigit(i))
-    {
-    p[cbit_digit  + i/8] |= 1 << (i&7);
-    p[cbit_word   + i/8] |= 1 << (i&7);
-    }
-  if (isupper(i))
-    {
-    p[cbit_upper  + i/8] |= 1 << (i&7);
-    p[cbit_word   + i/8] |= 1 << (i&7);
-    }
-  if (islower(i))
-    {
-    p[cbit_lower  + i/8] |= 1 << (i&7);
-    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 */
-
-for (i = 0; i < 256; i++)
-  {
-  int x = 0;
-  if (isspace(i)) x += ctype_space;
-  if (isalpha(i)) x += ctype_letter;
-  if (isdigit(i)) x += ctype_digit;
-  if (isxdigit(i)) x += ctype_xdigit;
-  if (isalnum(i) || i == '_') x += ctype_word;
-  if (strchr("*+?{^.$|()[", i) != 0) x += ctype_meta;
-  *p++ = x;
-  }
-
-return yield;
+        return yield;
 }
 
-/* ____ END maketables.c ____ */
-
-#ifdef L2_UT_PCRE_GENTAB
-
-/* ____ BEGIN dftables.c ____ */
-
-/* This is a support program to generate the file chartables.c, containing
-character tables of various kinds. They are built according to the default C
-locale and used as the default tables by PCRE. 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 L2_UT_PCRE_TAB
 
 #include <ctype.h>
 #include <stdio.h>
@@ -5757,94 +4199,78 @@
 
 int main(void)
 {
-int i;
-const unsigned char *tables = pcre_maketables();
+        int i;
+        const unsigned char *tables = pcre_maketables();
 
-printf(
-  "/*************************************************\n"
-  "*      Perl-Compatible Regular Expressions       *\n"
-  "*************************************************/\n\n"
-  "static unsigned char pcre_default_tables[] = {\n\n"
-  "/* This table is a lower casing table. */\n\n");
-
-printf("  ");
-for (i = 0; i < 256; i++)
-  {
-  if ((i & 7) == 0 && i != 0) printf("\n  ");
-  printf("%3d", *tables++);
-  if (i != 255) printf(",");
-  }
-printf(",\n\n");
-
-printf("/* This table is a case flipping table. */\n\n");
-
-printf("  ");
-for (i = 0; i < 256; i++)
-  {
-  if ((i & 7) == 0 && i != 0) printf("\n  ");
-  printf("%3d", *tables++);
-  if (i != 255) printf(",");
-  }
-printf(",\n\n");
-
-printf(
-  "/* 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");
-
-printf("  ");
-for (i = 0; i < cbit_length; i++)
-  {
-  if ((i & 7) == 0 && i != 0)
-    {
-    if ((i & 31) == 0) printf("\n");
-    printf("\n  ");
-    }
-  printf("0x%02x", *tables++);
-  if (i != cbit_length - 1) printf(",");
-  }
-printf(",\n\n");
-
-printf(
-  "/* 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);
-
-printf("  ");
-for (i = 0; i < 256; i++)
-  {
-  if ((i & 7) == 0 && i != 0)
-    {
-    printf(" /* ");
-    if (isprint(i-8)) printf(" %c -", i-8);
-      else printf("%3d-", i-8);
-    if (isprint(i-1)) printf(" %c ", i-1);
-      else printf("%3d", i-1);
-    printf(" */\n  ");
-    }
-  printf("0x%02x", *tables++);
-  if (i != 255) printf(",");
-  }
-
-printf("};/* ");
-if (isprint(i-8)) printf(" %c -", i-8);
-  else printf("%3d-", i-8);
-if (isprint(i-1)) printf(" %c ", i-1);
-  else printf("%3d", i-1);
-printf(" */\n\n\n");
+        printf("/*************************************************\n"
+                   "*      Perl-Compatible Regular Expressions       *\n"
+                   "*************************************************/\n\n"
+                   "static unsigned char pcre_default_tables[] = {\n\n"
+                   "/* This table is a lower casing table. */\n\n");
+
+        printf("  ");
+        for (i = 0; i < 256; i++) {
+                if ((i & 7) == 0 && i != 0)
+                        printf("\n  ");
+                printf("%3d", *tables++);
+                if (i != 255)
+                        printf(",");
+        }
+        printf(",\n\n");
+
+        printf("/* This table is a case flipping table. */\n\n");
+
+        printf("  ");
+        for (i = 0; i < 256; i++) {
+                if ((i & 7) == 0 && i != 0)
+                        printf("\n  ");
+                printf("%3d", *tables++);
+                if (i != 255)
+                        printf(",");
+        }
+        printf(",\n\n");
+
+        printf("/* 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");
+
+        printf("  ");
+        for (i = 0; i < cbit_length; i++) {
+                if ((i & 7) == 0 && i != 0) {
+                        if ((i & 31) == 0)
+                                printf("\n");
+                        printf("\n  ");
+                }
+                printf("0x%02x", *tables++);
+                if (i != cbit_length - 1)
+                        printf(",");
+        }
+        printf(",\n\n");
+
+        printf
+                ("/* 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);
+
+        printf("  ");
+        for (i = 0; i < 256; i++) {
+                if ((i & 7) == 0 && i != 0) {
+                        printf(" \n  ");
+                }
+                printf("0x%02x", *tables++);
+                if (i != 255)
+                        printf(",");
+        }
 
-return 0;
-}
+        printf("};\n\n\n");
 
-/* ____ END dftables.c ____ */
-
-#endif /* L2_UT_PCRE_GENTAB */
+        return 0;
+}
 
+#endif


ossp-pkg/l2/l2_ut_pcre.h 1.1 -> 1.2

--- l2_ut_pcre.h 2001/09/04 14:52:28     1.1
+++ l2_ut_pcre.h 2001/09/15 16:03:37     1.2
@@ -1,6 +1,16 @@
-/*************************************************
-*      Perl-Compatible Regular Expressions       *
-*************************************************/
+/*
+ *  Perl Compatible Regular Expression (PCRE) Library
+ *  Copyright (c) 1997-2001 Philip Hazel <ph10@cam.ac.uk>
+ *  Copyright (c) 1997-2001 University of Cambridge
+ *
+ *  DO NOT EDIT THIS FILE, IT WAS AUTOMATICALLY GENERATED!
+ *
+ *  This is an automatically generated, extremely stripped down
+ *  version of the PCRE 3.5 library from the Philip Hazel.
+ *  This version is still distributed under the same original PCRE
+ *  Open Source license, but Philip Hazel is no longer responsible
+ *  for this version.
+ */
 
 /*
 This is a library of functions to support regular expressions whose syntax
@@ -35,26 +45,16 @@
 #ifndef __L2_UT_PCRE_H__
 #define __L2_UT_PCRE_H__
 
-/* The file pcre.h is build by "configure". Do not edit it; instead
-make changes to pcre.in. */
-
 #define PCRE_MAJOR          3
 #define PCRE_MINOR          5
 #define PCRE_DATE           15-Aug-2001
 
-/* Have to include stdlib.h in order to ensure that size_t is defined;
-it is needed here for malloc. */
-
 #include <stdlib.h>
 
-/* Allow for C++ users */
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* Options */
-
 #define PCRE_CASELESS        0x0001
 #define PCRE_MULTILINE       0x0002
 #define PCRE_DOTALL          0x0004
@@ -68,8 +68,6 @@
 #define PCRE_NOTEMPTY        0x0400
 #define PCRE_UTF8            0x0800
 
-/* Exec-time and get-time error codes */
-
 #define PCRE_ERROR_NOMATCH        (-1)
 #define PCRE_ERROR_NULL           (-2)
 #define PCRE_ERROR_BADOPTION      (-3)
@@ -78,8 +76,6 @@
 #define PCRE_ERROR_NOMEMORY       (-6)
 #define PCRE_ERROR_NOSUBSTRING    (-7)
 
-/* Request types for pcre_fullinfo() */
-
 #define PCRE_INFO_OPTIONS         0
 #define PCRE_INFO_SIZE            1
 #define PCRE_INFO_CAPTURECOUNT    2
@@ -88,23 +84,15 @@
 #define PCRE_INFO_FIRSTTABLE      5
 #define PCRE_INFO_LASTLITERAL     6
 
-/* Types */
-
-struct real_pcre;        /* declaration; the definition is private  */
-struct real_pcre_extra;  /* declaration; the definition is private */
+struct real_pcre;
+struct real_pcre_extra;
 
 typedef struct real_pcre pcre;
 typedef struct real_pcre_extra pcre_extra;
 
-/* Store get and free functions. These can be set to alternative malloc/free
-functions if required. Some magic is required for Win32 DLL; it is null on
-other OS. */
-
 extern void *(*pcre_malloc)(size_t);
 extern void  (*pcre_free)(void *);
 
-/* Functions */
-
 extern pcre *pcre_compile(const char *, int, const char **, int *,
               const unsigned char *);
 extern int  pcre_copy_substring(const char *, int *, int, int, char *, int);
@@ -121,7 +109,7 @@
 extern const char *pcre_version(void);
 
 #ifdef __cplusplus
-}  /* extern "C" */
+}
 #endif
 
-#endif /* __L2_UT_PCRE_H__ */
+#endif

CVSTrac 2.0.1