bugzilla 612 - write recipients list in X-Envelope-To header of MBOX spool file
[exim.git] / src / src / pcre / pcre_compile.c
index f7a3ebbd248c13750e3bc4579c5360d5f45b6779..98c307947c0ff7c03f391f01378109e243f90721 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/pcre/pcre_compile.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/pcre/pcre_compile.c,v 1.6 2007/11/12 13:02:19 nm4 Exp $ */
 
 /*************************************************
 *      Perl-Compatible Regular Expressions       *
@@ -8,7 +8,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
+           Copyright (c) 1997-2007 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -44,11 +44,14 @@ POSSIBILITY OF SUCH DAMAGE.
 supporting internal functions that are not used by other modules. */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #define NLBLOCK cd             /* Block containing newline information */
 #define PSSTART start_pattern  /* Field containing processed string start */
 #define PSEND   end_pattern    /* Field containing processed string end */
 
-
 #include "pcre_internal.h"
 
 
@@ -60,6 +63,18 @@ used by pcretest. DEBUG is not defined when building a production library. */
 #endif
 
 
+/* Macro for setting individual bits in class bitmaps. */
+
+#define SETBIT(a,b) a[b/8] |= (1 << (b%8))
+
+/* Maximum length value to check against when making sure that the integer that
+holds the compiled pattern length does not overflow. We make it a bit less than
+INT_MAX to allow for adding in group terminating bytes, so that we don't have
+to check them every time. */
+
+#define OFLOW_MAX (INT_MAX - 20)
+
+
 /*************************************************
 *      Code parameters and static tables         *
 *************************************************/
@@ -84,21 +99,21 @@ 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. */
 
-#if !EBCDIC   /* This is the "normal" table for ASCII systems */
+#ifndef EBCDIC  /* This is the "normal" table for ASCII systems */
 static const short int escapes[] = {
      0,      0,      0,      0,      0,      0,      0,      0,   /* 0 - 7 */
      0,      0,    ':',    ';',    '<',    '=',    '>',    '?',   /* 8 - ? */
    '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E,      0, -ESC_G,   /* @ - G */
-     0,      0,      0,      0,      0,      0,      0,      0,   /* H - O */
--ESC_P, -ESC_Q, -ESC_R, -ESC_S,      0,      0,      0, -ESC_W,   /* P - W */
+-ESC_H,      0,      0, -ESC_K,      0,      0,      0,      0,   /* H - O */
+-ESC_P, -ESC_Q, -ESC_R, -ESC_S,      0,      0, -ESC_V, -ESC_W,   /* P - W */
 -ESC_X,      0, -ESC_Z,    '[',   '\\',    ']',    '^',    '_',   /* X - _ */
    '`',      7, -ESC_b,      0, -ESC_d,  ESC_e,  ESC_f,      0,   /* ` - g */
-     0,      0,      0, -ESC_k,      0,      0,  ESC_n,      0,   /* h - o */
--ESC_p,      0,  ESC_r, -ESC_s,  ESC_tee,    0,      0, -ESC_w,   /* p - w */
+-ESC_h,      0,      0, -ESC_k,      0,      0,  ESC_n,      0,   /* h - o */
+-ESC_p,      0,  ESC_r, -ESC_s,  ESC_tee,    0, -ESC_v, -ESC_w,   /* p - w */
      0,      0, -ESC_z                                            /* x - z */
 };
 
-#else         /* This is the "abnormal" table for EBCDIC systems */
+#else           /* This is the "abnormal" table for EBCDIC systems */
 static const short int escapes[] = {
 /*  48 */     0,     0,      0,     '.',    '<',   '(',    '+',    '|',
 /*  50 */   '&',     0,      0,       0,      0,     0,      0,      0,
@@ -108,18 +123,18 @@ static const short int escapes[] = {
 /*  70 */     0,     0,      0,       0,      0,     0,      0,      0,
 /*  78 */     0,   '`',    ':',     '#',    '@',  '\'',    '=',    '"',
 /*  80 */     0,     7, -ESC_b,       0, -ESC_d, ESC_e,  ESC_f,      0,
-/*  88 */     0,     0,      0,     '{',      0,     0,      0,      0,
+/*  88 */-ESC_h,     0,      0,     '{',      0,     0,      0,      0,
 /*  90 */     0,     0, -ESC_k,     'l',      0, ESC_n,      0, -ESC_p,
 /*  98 */     0, ESC_r,      0,     '}',      0,     0,      0,      0,
-/*  A0 */     0,   '~', -ESC_s, ESC_tee,      0,     0, -ESC_w,      0,
+/*  A0 */     0,   '~', -ESC_s, ESC_tee,      0,-ESC_v, -ESC_w,      0,
 /*  A8 */     0,-ESC_z,      0,       0,      0,   '[',      0,      0,
 /*  B0 */     0,     0,      0,       0,      0,     0,      0,      0,
 /*  B8 */     0,     0,      0,       0,      0,   ']',    '=',    '-',
 /*  C0 */   '{',-ESC_A, -ESC_B,  -ESC_C, -ESC_D,-ESC_E,      0, -ESC_G,
-/*  C8 */     0,     0,      0,       0,      0,     0,      0,      0,
-/*  D0 */   '}',     0,      0,       0,      0,     0,      0, -ESC_P,
+/*  C8 */-ESC_H,     0,      0,       0,      0,     0,      0,      0,
+/*  D0 */   '}',     0, -ESC_K,       0,      0,     0,      0, -ESC_P,
 /*  D8 */-ESC_Q,-ESC_R,      0,       0,      0,     0,      0,      0,
-/*  E0 */  '\\',     0, -ESC_S,       0,      0,     0, -ESC_W, -ESC_X,
+/*  E0 */  '\\',     0, -ESC_S,       0,      0,-ESC_V, -ESC_W, -ESC_X,
 /*  E8 */     0,-ESC_Z,      0,       0,      0,     0,      0,      0,
 /*  F0 */     0,     0,      0,       0,      0,     0,      0,      0,
 /*  F8 */     0,     0,      0,       0,      0,     0,      0,      0
@@ -127,14 +142,47 @@ static const short int escapes[] = {
 #endif
 
 
-/* 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, lower, upper,
-as this is assumed for handling case independence. */
+/* Table of special "verbs" like (*PRUNE). This is a short table, so it is
+searched linearly. Put all the names into a single string, in order to reduce
+the number of relocations when a shared library is dynamically linked. */
+
+typedef struct verbitem {
+  int   len;
+  int   op;
+} verbitem;
+
+static const char verbnames[] =
+  "ACCEPT\0"
+  "COMMIT\0"
+  "F\0"
+  "FAIL\0"
+  "PRUNE\0"
+  "SKIP\0"
+  "THEN";
+
+static verbitem verbs[] = {
+  { 6, OP_ACCEPT },
+  { 6, OP_COMMIT },
+  { 1, OP_FAIL },
+  { 4, OP_FAIL },
+  { 5, OP_PRUNE },
+  { 4, OP_SKIP  },
+  { 4, OP_THEN  }
+};
+
+static int verbcount = sizeof(verbs)/sizeof(verbitem);
+
+
+/* Tables of names of POSIX character classes and their lengths. The names are
+now all in a single string, to reduce the number of relocations when a shared
+library is dynamically loaded. The list of lengths is terminated by a zero
+length entry. The first three must be alpha, lower, upper, as this is assumed
+for handling case independence. */
 
-static const char *const posix_names[] = {
-  "alpha", "lower", "upper",
-  "alnum", "ascii", "blank", "cntrl", "digit", "graph",
-  "print", "punct", "space", "word",  "xdigit" };
+static const char posix_names[] =
+  "alpha\0"  "lower\0"  "upper\0"  "alnum\0"  "ascii\0"  "blank\0"
+  "cntrl\0"  "digit\0"  "graph\0"  "print\0"  "punct\0"  "space\0"
+  "word\0"   "xdigit";
 
 static const uschar posix_name_lengths[] = {
   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
@@ -173,79 +221,88 @@ static const int posix_class_maps[] = {
 /* The texts of compile-time error messages. These are "char *" because they
 are passed to the outside world. Do not ever re-use any error number, because
 they are documented. Always add a new error instead. Messages marked DEAD below
-are no longer used. */
-
-static const char *error_texts[] = {
-  "no error",
-  "\\ at end of pattern",
-  "\\c at end of pattern",
-  "unrecognized character follows \\",
-  "numbers out of order in {} quantifier",
+are no longer used. This used to be a table of strings, but in order to reduce
+the number of relocations needed when a shared library is loaded dynamically,
+it is now one long string. We cannot use a table of offsets, because the
+lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we
+simply count through to the one we want - this isn't a performance issue
+because these strings are used only when there is a compilation error. */
+
+static const char error_texts[] =
+  "no error\0"
+  "\\ at end of pattern\0"
+  "\\c at end of pattern\0"
+  "unrecognized character follows \\\0"
+  "numbers out of order in {} quantifier\0"
   /* 5 */
-  "number too big in {} quantifier",
-  "missing terminating ] for character class",
-  "invalid escape sequence in character class",
-  "range out of order in character class",
-  "nothing to repeat",
+  "number too big in {} quantifier\0"
+  "missing terminating ] for character class\0"
+  "invalid escape sequence in character class\0"
+  "range out of order in character class\0"
+  "nothing to repeat\0"
   /* 10 */
-  "operand of unlimited repeat could match the empty string",  /** DEAD **/
-  "internal error: unexpected repeat",
-  "unrecognized character after (?",
-  "POSIX named classes are supported only within a class",
-  "missing )",
+  "operand of unlimited repeat could match the empty string\0"  /** DEAD **/
+  "internal error: unexpected repeat\0"
+  "unrecognized character after (?\0"
+  "POSIX named classes are supported only within a class\0"
+  "missing )\0"
   /* 15 */
-  "reference to non-existent subpattern",
-  "erroffset passed as NULL",
-  "unknown option bit(s) set",
-  "missing ) after comment",
-  "parentheses nested too deeply",  /** DEAD **/
+  "reference to non-existent subpattern\0"
+  "erroffset passed as NULL\0"
+  "unknown option bit(s) set\0"
+  "missing ) after comment\0"
+  "parentheses nested too deeply\0"  /** DEAD **/
   /* 20 */
-  "regular expression too large",
-  "failed to get memory",
-  "unmatched parentheses",
-  "internal error: code overflow",
-  "unrecognized character after (?<",
+  "regular expression is too large\0"
+  "failed to get memory\0"
+  "unmatched parentheses\0"
+  "internal error: code overflow\0"
+  "unrecognized character after (?<\0"
   /* 25 */
-  "lookbehind assertion is not fixed length",
-  "malformed number or name after (?(",
-  "conditional group contains more than two branches",
-  "assertion expected after (?(",
-  "(?R or (?digits must be followed by )",
+  "lookbehind assertion is not fixed length\0"
+  "malformed number or name after (?(\0"
+  "conditional group contains more than two branches\0"
+  "assertion expected after (?(\0"
+  "(?R or (?[+-]digits must be followed by )\0"
   /* 30 */
-  "unknown POSIX class name",
-  "POSIX collating elements are not supported",
-  "this version of PCRE is not compiled with PCRE_UTF8 support",
-  "spare error",  /** DEAD **/
-  "character value in \\x{...} sequence is too large",
+  "unknown POSIX class name\0"
+  "POSIX collating elements are not supported\0"
+  "this version of PCRE is not compiled with PCRE_UTF8 support\0"
+  "spare error\0"  /** DEAD **/
+  "character value in \\x{...} sequence is too large\0"
   /* 35 */
-  "invalid condition (?(0)",
-  "\\C not allowed in lookbehind assertion",
-  "PCRE does not support \\L, \\l, \\N, \\U, or \\u",
-  "number after (?C is > 255",
-  "closing ) for (?C expected",
+  "invalid condition (?(0)\0"
+  "\\C not allowed in lookbehind assertion\0"
+  "PCRE does not support \\L, \\l, \\N, \\U, or \\u\0"
+  "number after (?C is > 255\0"
+  "closing ) for (?C expected\0"
   /* 40 */
-  "recursive call could loop indefinitely",
-  "unrecognized character after (?P",
-  "syntax error in subpattern name (missing terminator)",
-  "two named subpatterns have the same name",
-  "invalid UTF-8 string",
+  "recursive call could loop indefinitely\0"
+  "unrecognized character after (?P\0"
+  "syntax error in subpattern name (missing terminator)\0"
+  "two named subpatterns have the same name\0"
+  "invalid UTF-8 string\0"
   /* 45 */
-  "support for \\P, \\p, and \\X has not been compiled",
-  "malformed \\P or \\p sequence",
-  "unknown property name after \\P or \\p",
-  "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)",
-  "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")",
+  "support for \\P, \\p, and \\X has not been compiled\0"
+  "malformed \\P or \\p sequence\0"
+  "unknown property name after \\P or \\p\0"
+  "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0"
+  "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
   /* 50 */
-  "repeated subpattern is too long",
-  "octal value is greater than \\377 (not in UTF-8 mode)",
-  "internal error: overran compiling workspace",
-  "internal error: previously-checked referenced subpattern not found",
-  "DEFINE group contains more than one branch",
+  "repeated subpattern is too long\0"    /** DEAD **/
+  "octal value is greater than \\377 (not in UTF-8 mode)\0"
+  "internal error: overran compiling workspace\0"
+  "internal error: previously-checked referenced subpattern not found\0"
+  "DEFINE group contains more than one branch\0"
   /* 55 */
-  "repeating a DEFINE group is not allowed",
-  "inconsistent NEWLINE options",
-  "\\g is not followed by an (optionally braced) non-zero number"
-};
+  "repeating a DEFINE group is not allowed\0"
+  "inconsistent NEWLINE options\0"
+  "\\g is not followed by a braced name or an optionally braced non-zero number\0"
+  "(?+ or (?- or (?(+ or (?(- must be followed by a non-zero number\0"
+  "(*VERB) with an argument is not supported\0"
+  /* 60 */
+  "(*VERB) not recognized\0"
+  "number is too big";
 
 
 /* Table to identify digits and hex digits. This is used when compiling
@@ -264,7 +321,7 @@ For convenience, we use the same bit definitions as in chartables:
 
 Then we can use ctype_digit and ctype_xdigit in the code. */
 
-#if !EBCDIC    /* This is the "normal" case, for ASCII systems */
+#ifndef EBCDIC  /* This is the "normal" case, for ASCII systems */
 static const unsigned char digitab[] =
   {
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7 */
@@ -300,7 +357,7 @@ static const unsigned char digitab[] =
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
 
-#else          /* This is the "abnormal" case, for EBCDIC systems */
+#else           /* This is the "abnormal" case, for EBCDIC systems */
 static const unsigned char digitab[] =
   {
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7  0 */
@@ -314,7 +371,7 @@ static const unsigned char digitab[] =
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*    - 71 40 */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  72- |     */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  & - 87 50 */
-  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  88- ¬     */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  88- 95    */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  - -103 60 */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ?     */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */
@@ -348,7 +405,7 @@ static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */
   0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*    - 71 */
   0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /*  72- |  */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  & - 87 */
-  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /*  88- ¬  */
+  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /*  88- 95 */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  - -103 */
   0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ?  */
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */
@@ -375,11 +432,33 @@ static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */
 /* Definition to allow mutual recursion */
 
 static BOOL
-  compile_regex(int, int, uschar **, const uschar **, int *, BOOL, int, int *,
-    int *, branch_chain *, compile_data *, int *);
+  compile_regex(int, int, uschar **, const uschar **, int *, BOOL, BOOL, int,
+    int *, int *, branch_chain *, compile_data *, int *);
 
 
 
+/*************************************************
+*            Find an error text                  *
+*************************************************/
+
+/* The error texts are now all in one long string, to save on relocations. As
+some of the text is of unknown length, we can't use a table of offsets.
+Instead, just count through the strings. This is not a performance issue
+because it happens only when there has been a compilation error.
+
+Argument:   the error number
+Returns:    pointer to the error string
+*/
+
+static const char *
+find_error_text(int n)
+{
+const char *s = error_texts;
+for (; n > 0; n--) while (*s++ != 0);
+return s;
+}
+
+
 /*************************************************
 *            Handle escapes                      *
 *************************************************/
@@ -401,7 +480,7 @@ Arguments:
 
 Returns:         zero or positive => a data character
                  negative => a special escape sequence
-                 on error, errorptr is set
+                 on error, errorcodeptr is set
 */
 
 static int
@@ -423,11 +502,11 @@ if (c == 0) *errorcodeptr = ERR1;
 a table. A non-zero result is something that can be returned immediately.
 Otherwise further processing may be required. */
 
-#if !EBCDIC    /* ASCII coding */
+#ifndef EBCDIC  /* ASCII coding */
 else if (c < '0' || c > 'z') {}                           /* Not alphameric */
 else if ((i = escapes[c - '0']) != 0) c = i;
 
-#else          /* EBCDIC coding */
+#else           /* EBCDIC coding */
 else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {}   /* Not alphameric */
 else if ((i = escapes[c - 0x48]) != 0)  c = i;
 #endif
@@ -454,11 +533,22 @@ else
 
     /* \g must be followed by a number, either plain or braced. If positive, it
     is an absolute backreference. If negative, it is a relative backreference.
-    This is a Perl 5.10 feature. */
+    This is a Perl 5.10 feature. Perl 5.10 also supports \g{name} as a
+    reference to a named group. This is part of Perl's movement towards a
+    unified syntax for back references. As this is synonymous with \k{name}, we
+    fudge it up by pretending it really was \k. */
 
     case 'g':
     if (ptr[1] == '{')
       {
+      const uschar *p;
+      for (p = ptr+2; *p != 0 && *p != '}'; p++)
+        if (*p != '-' && (digitab[*p] & ctype_digit) == 0) break;
+      if (*p != 0 && *p != '}')
+        {
+        c = -ESC_k;
+        break;
+        }
       braced = TRUE;
       ptr++;
       }
@@ -475,10 +565,16 @@ else
     while ((digitab[ptr[1]] & ctype_digit) != 0)
       c = c * 10 + *(++ptr) - '0';
 
+    if (c < 0)
+      {
+      *errorcodeptr = ERR61;
+      break;
+      }
+
     if (c == 0 || (braced && *(++ptr) != '}'))
       {
       *errorcodeptr = ERR57;
-      return 0;
+      break;
       }
 
     if (negated)
@@ -486,7 +582,7 @@ else
       if (c > bracount)
         {
         *errorcodeptr = ERR15;
-        return 0;
+        break;
         }
       c = bracount - (c - 1);
       }
@@ -515,6 +611,11 @@ else
       c -= '0';
       while ((digitab[ptr[1]] & ctype_digit) != 0)
         c = c * 10 + *(++ptr) - '0';
+      if (c < 0)
+        {
+        *errorcodeptr = ERR61;
+        break;
+        }
       if (c < 10 || c <= bracount)
         {
         c = -(ESC_REF + c);
@@ -564,10 +665,10 @@ else
         if (c == 0 && cc == '0') continue;     /* Leading zeroes */
         count++;
 
-#if !EBCDIC    /* ASCII coding */
+#ifndef EBCDIC  /* ASCII coding */
         if (cc >= 'a') cc -= 32;               /* Convert to upper case */
         c = (c << 4) + cc - ((cc < 'A')? '0' : ('A' - 10));
-#else          /* EBCDIC coding */
+#else           /* EBCDIC coding */
         if (cc >= 'a' && cc <= 'z') cc += 64;  /* Convert to upper case */
         c = (c << 4) + cc - ((cc >= '0')? '0' : ('A' - 10));
 #endif
@@ -591,10 +692,10 @@ else
       {
       int cc;                               /* Some compilers don't like ++ */
       cc = *(++ptr);                        /* in initializers */
-#if !EBCDIC    /* ASCII coding */
+#ifndef EBCDIC  /* ASCII coding */
       if (cc >= 'a') cc -= 32;              /* Convert to upper case */
       c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10));
-#else          /* EBCDIC coding */
+#else           /* EBCDIC coding */
       if (cc <= 'z') cc += 64;              /* Convert to upper case */
       c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10));
 #endif
@@ -610,13 +711,13 @@ else
     if (c == 0)
       {
       *errorcodeptr = ERR2;
-      return 0;
+      break;
       }
 
-#if !EBCDIC    /* ASCII coding */
+#ifndef EBCDIC  /* ASCII coding */
     if (c >= 'a' && c <= 'z') c -= 32;
     c ^= 0x40;
-#else          /* EBCDIC coding */
+#else           /* EBCDIC coding */
     if (c >= 'a' && c <= 'z') c += 64;
     c ^= 0xC0;
 #endif
@@ -686,7 +787,7 @@ if (c == '{')
     *negptr = TRUE;
     ptr++;
     }
-  for (i = 0; i < sizeof(name) - 1; i++)
+  for (i = 0; i < (int)sizeof(name) - 1; i++)
     {
     c = *(++ptr);
     if (c == 0) goto ERROR_RETURN;
@@ -715,7 +816,7 @@ top = _pcre_utt_size;
 while (bot < top)
   {
   i = (bot + top) >> 1;
-  c = strcmp(name, _pcre_utt[i].name);
+  c = strcmp(name, _pcre_utt_names + _pcre_utt[i].name_offset);
   if (c == 0)
     {
     *dptr = _pcre_utt[i].value;
@@ -889,6 +990,7 @@ for (; *ptr != 0; ptr++)
     {
     while (*(++ptr) != ']')
       {
+      if (*ptr == 0) return -1;
       if (*ptr == '\\')
         {
         if (*(++ptr) == 0) return -1;
@@ -916,7 +1018,7 @@ for (; *ptr != 0; ptr++)
   /* An opening parens must now be a real metacharacter */
 
   if (*ptr != '(') continue;
-  if (ptr[1] != '?')
+  if (ptr[1] != '?' && ptr[1] != '*')
     {
     count++;
     if (name == NULL && count == lorn) return count;
@@ -1044,7 +1146,6 @@ for (;;)
   {
   int d;
   register int op = *cc;
-
   switch (op)
     {
     case OP_CBRA:
@@ -1133,6 +1234,7 @@ for (;;)
 
     case OP_TYPEEXACT:
     branchlength += GET2(cc,1);
+    if (cc[3] == OP_PROP || cc[3] == OP_NOTPROP) cc += 2;
     cc += 4;
     break;
 
@@ -1241,13 +1343,43 @@ for (;;)
     code += _pcre_OP_lengths[c];
     }
 
-  /* In UTF-8 mode, opcodes that are followed by a character may be followed by
-  a multi-byte character. The length in the table is a minimum, so we have to
-  arrange to skip the extra bytes. */
+  /* Otherwise, we can get the item's length from the table, except that for
+  repeated character types, we have to test for \p and \P, which have an extra
+  two bytes of parameters. */
 
   else
     {
+    switch(c)
+      {
+      case OP_TYPESTAR:
+      case OP_TYPEMINSTAR:
+      case OP_TYPEPLUS:
+      case OP_TYPEMINPLUS:
+      case OP_TYPEQUERY:
+      case OP_TYPEMINQUERY:
+      case OP_TYPEPOSSTAR:
+      case OP_TYPEPOSPLUS:
+      case OP_TYPEPOSQUERY:
+      if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+      break;
+
+      case OP_TYPEUPTO:
+      case OP_TYPEMINUPTO:
+      case OP_TYPEEXACT:
+      case OP_TYPEPOSUPTO:
+      if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
+      break;
+      }
+
+    /* Add in the fixed length from the table */
+
     code += _pcre_OP_lengths[c];
+
+  /* In UTF-8 mode, opcodes that are followed by a character may be followed by
+  a multi-byte character. The length in the table is a minimum, so we have to
+  arrange to skip the extra bytes. */
+
+#ifdef SUPPORT_UTF8
     if (utf8) switch(c)
       {
       case OP_CHAR:
@@ -1268,6 +1400,7 @@ for (;;)
       if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f];
       break;
       }
+#endif
     }
   }
 }
@@ -1303,14 +1436,43 @@ for (;;)
 
   if (c == OP_XCLASS) code += GET(code, 1);
 
-  /* Otherwise, we get the item's length from the table. In UTF-8 mode, opcodes
-  that are followed by a character may be followed by a multi-byte character.
-  The length in the table is a minimum, so we have to arrange to skip the extra
-  bytes. */
+  /* Otherwise, we can get the item's length from the table, except that for
+  repeated character types, we have to test for \p and \P, which have an extra
+  two bytes of parameters. */
 
   else
     {
+    switch(c)
+      {
+      case OP_TYPESTAR:
+      case OP_TYPEMINSTAR:
+      case OP_TYPEPLUS:
+      case OP_TYPEMINPLUS:
+      case OP_TYPEQUERY:
+      case OP_TYPEMINQUERY:
+      case OP_TYPEPOSSTAR:
+      case OP_TYPEPOSPLUS:
+      case OP_TYPEPOSQUERY:
+      if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+      break;
+
+      case OP_TYPEPOSUPTO:
+      case OP_TYPEUPTO:
+      case OP_TYPEMINUPTO:
+      case OP_TYPEEXACT:
+      if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
+      break;
+      }
+
+    /* Add in the fixed length from the table */
+
     code += _pcre_OP_lengths[c];
+
+    /* In UTF-8 mode, opcodes that are followed by a character may be followed
+    by a multi-byte character. The length in the table is a minimum, so we have
+    to arrange to skip the extra bytes. */
+
+#ifdef SUPPORT_UTF8
     if (utf8) switch(c)
       {
       case OP_CHAR:
@@ -1331,6 +1493,7 @@ for (;;)
       if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f];
       break;
       }
+#endif
     }
   }
 }
@@ -1368,7 +1531,19 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE
 
   c = *code;
 
-  if (c == OP_BRA || c == OP_CBRA || c == OP_ONCE)
+  /* Groups with zero repeats can of course be empty; skip them. */
+
+  if (c == OP_BRAZERO || c == OP_BRAMINZERO)
+    {
+    code += _pcre_OP_lengths[c];
+    do code += GET(code, 1); while (*code == OP_ALT);
+    c = *code;
+    continue;
+    }
+
+  /* For other groups, scan the branches. */
+
+  if (c == OP_BRA || c == OP_CBRA || c == OP_ONCE || c == OP_COND)
     {
     BOOL empty_branch;
     if (GET(code, 1) == 0) return TRUE;    /* Hit unclosed bracket */
@@ -1384,12 +1559,7 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE
       }
     while (*code == OP_ALT);
     if (!empty_branch) return FALSE;   /* All branches are non-empty */
-
-    /* Move past the KET and fudge things so that the increment in the "for"
-    above has no effect. */
-
-    c = OP_END;
-    code += 1 + LINK_SIZE - _pcre_OP_lengths[c];
+    c = *code;
     continue;
     }
 
@@ -1397,11 +1567,15 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE
 
   switch (c)
     {
-    /* Check for quantifiers after a class */
+    /* Check for quantifiers after a class. XCLASS is used for classes that
+    cannot be represented just by a bit map. This includes negated single
+    high-valued characters. The length in _pcre_OP_lengths[] is zero; the
+    actual length is stored in the compiled code, so we must update "code"
+    here. */
 
 #ifdef SUPPORT_UTF8
     case OP_XCLASS:
-    ccode = code + GET(code, 1);
+    ccode = code += GET(code, 1);
     goto CHECK_CLASS_REPEAT;
 #endif
 
@@ -1463,6 +1637,26 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE
     case OP_TYPEEXACT:
     return FALSE;
 
+    /* These are going to continue, as they may be empty, but we have to
+    fudge the length for the \p and \P cases. */
+
+    case OP_TYPESTAR:
+    case OP_TYPEMINSTAR:
+    case OP_TYPEPOSSTAR:
+    case OP_TYPEQUERY:
+    case OP_TYPEMINQUERY:
+    case OP_TYPEPOSQUERY:
+    if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+    break;
+
+    /* Same for these */
+
+    case OP_TYPEUPTO:
+    case OP_TYPEMINUPTO:
+    case OP_TYPEPOSUPTO:
+    if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
+    break;
+
     /* End of branch */
 
     case OP_KET:
@@ -1579,11 +1773,13 @@ Returns:     a value representing the name, or -1 if unknown
 static int
 check_posix_name(const uschar *ptr, int len)
 {
+const char *pn = posix_names;
 register int yield = 0;
 while (posix_name_lengths[yield] != 0)
   {
   if (len == posix_name_lengths[yield] &&
-    strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
+    strncmp((const char *)ptr, pn, len) == 0) return yield;
+  pn += posix_name_lengths[yield] + 1;
   yield++;
   }
 return -1;
@@ -1625,6 +1821,7 @@ adjust_recurse(uschar *group, int adjust, BOOL utf8, compile_data *cd,
   uschar *save_hwm)
 {
 uschar *ptr = group;
+
 while ((ptr = (uschar *)find_recurse(ptr, utf8)) != NULL)
   {
   int offset;
@@ -1923,6 +2120,50 @@ if (next >= 0) switch(op_code)
   case OP_NOT_WORDCHAR:
   return next <= 127 && (cd->ctypes[next] & ctype_word) != 0;
 
+  case OP_HSPACE:
+  case OP_NOT_HSPACE:
+  switch(next)
+    {
+    case 0x09:
+    case 0x20:
+    case 0xa0:
+    case 0x1680:
+    case 0x180e:
+    case 0x2000:
+    case 0x2001:
+    case 0x2002:
+    case 0x2003:
+    case 0x2004:
+    case 0x2005:
+    case 0x2006:
+    case 0x2007:
+    case 0x2008:
+    case 0x2009:
+    case 0x200A:
+    case 0x202f:
+    case 0x205f:
+    case 0x3000:
+    return op_code != OP_HSPACE;
+    default:
+    return op_code == OP_HSPACE;
+    }
+
+  case OP_VSPACE:
+  case OP_NOT_VSPACE:
+  switch(next)
+    {
+    case 0x0a:
+    case 0x0b:
+    case 0x0c:
+    case 0x0d:
+    case 0x85:
+    case 0x2028:
+    case 0x2029:
+    return op_code != OP_VSPACE;
+    default:
+    return op_code == OP_VSPACE;
+    }
+
   default:
   return FALSE;
   }
@@ -1957,12 +2198,57 @@ switch(op_code)
     case ESC_W:
     return item <= 127 && (cd->ctypes[item] & ctype_word) != 0;
 
+    case ESC_h:
+    case ESC_H:
+    switch(item)
+      {
+      case 0x09:
+      case 0x20:
+      case 0xa0:
+      case 0x1680:
+      case 0x180e:
+      case 0x2000:
+      case 0x2001:
+      case 0x2002:
+      case 0x2003:
+      case 0x2004:
+      case 0x2005:
+      case 0x2006:
+      case 0x2007:
+      case 0x2008:
+      case 0x2009:
+      case 0x200A:
+      case 0x202f:
+      case 0x205f:
+      case 0x3000:
+      return -next != ESC_h;
+      default:
+      return -next == ESC_h;
+      }
+
+    case ESC_v:
+    case ESC_V:
+    switch(item)
+      {
+      case 0x0a:
+      case 0x0b:
+      case 0x0c:
+      case 0x0d:
+      case 0x85:
+      case 0x2028:
+      case 0x2029:
+      return -next != ESC_v;
+      default:
+      return -next == ESC_v;
+      }
+
     default:
     return FALSE;
     }
 
   case OP_DIGIT:
-  return next == -ESC_D || next == -ESC_s || next == -ESC_W;
+  return next == -ESC_D || next == -ESC_s || next == -ESC_W ||
+         next == -ESC_h || next == -ESC_v;
 
   case OP_NOT_DIGIT:
   return next == -ESC_d;
@@ -1971,10 +2257,23 @@ switch(op_code)
   return next == -ESC_S || next == -ESC_d || next == -ESC_w;
 
   case OP_NOT_WHITESPACE:
-  return next == -ESC_s;
+  return next == -ESC_s || next == -ESC_h || next == -ESC_v;
+
+  case OP_HSPACE:
+  return next == -ESC_S || next == -ESC_H || next == -ESC_d || next == -ESC_w;
+
+  case OP_NOT_HSPACE:
+  return next == -ESC_h;
+
+  /* Can't have \S in here because VT matches \S (Perl anomaly) */
+  case OP_VSPACE:
+  return next == -ESC_V || next == -ESC_d || next == -ESC_w;
+
+  case OP_NOT_VSPACE:
+  return next == -ESC_v;
 
   case OP_WORDCHAR:
-  return next == -ESC_W || next == -ESC_s;
+  return next == -ESC_W || next == -ESC_s || next == -ESC_h || next == -ESC_v;
 
   case OP_NOT_WORDCHAR:
   return next == -ESC_w || next == -ESC_d;
@@ -2089,10 +2388,12 @@ for (;; ptr++)
   BOOL possessive_quantifier;
   BOOL is_quantifier;
   BOOL is_recurse;
+  BOOL reset_bracount;
   int class_charcount;
   int class_lastchar;
   int newoptions;
   int recno;
+  int refsign;
   int skipbytes;
   int subreqbyte;
   int subfirstbyte;
@@ -2125,6 +2426,15 @@ for (;; ptr++)
     */
 
     if (code < last_code) code = last_code;
+
+    /* Paranoid check for integer overflow */
+
+    if (OFLOW_MAX - *lengthptr < code - last_code)
+      {
+      *errorcodeptr = ERR20;
+      goto FAILED;
+      }
+
     *lengthptr += code - last_code;
     DPRINTF(("length=%d added %d c=%c\n", *lengthptr, code - last_code, c));
 
@@ -2237,6 +2547,11 @@ for (;; ptr++)
     *ptrptr = ptr;
     if (lengthptr != NULL)
       {
+      if (OFLOW_MAX - *lengthptr < code - last_code)
+        {
+        *errorcodeptr = ERR20;
+        goto FAILED;
+        }
       *lengthptr += code - last_code;   /* To include callout length */
       DPRINTF((">> end branch\n"));
       }
@@ -2299,16 +2614,23 @@ for (;; ptr++)
       goto FAILED;
       }
 
-    /* If the first character is '^', set the negation flag and skip it. */
+    /* If the first character is '^', set the negation flag and skip it. Also,
+    if the first few characters (either before or after ^) are \Q\E or \E we
+    skip them too. This makes for compatibility with Perl. */
 
-    if ((c = *(++ptr)) == '^')
+    negate_class = FALSE;
+    for (;;)
       {
-      negate_class = TRUE;
       c = *(++ptr);
-      }
-    else
-      {
-      negate_class = FALSE;
+      if (c == '\\')
+        {
+        if (ptr[1] == 'E') ptr++;
+          else if (strncmp((const char *)ptr+1, "Q\\E", 3) == 0) ptr += 3;
+            else break;
+        }
+      else if (!negate_class && c == '^')
+        negate_class = TRUE;
+      else break;
       }
 
     /* Keep a count of chars with values < 256 so that we can optimize the case
@@ -2449,7 +2771,7 @@ for (;; ptr++)
       of the specials, which just set a flag. The sequence \b is a special
       case. Inside a class (and only there) it is treated as backspace.
       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
+      to 'or' into the one we are building. We assume they have more than one
       character in them, so set class_charcount bigger than one. */
 
       if (c == '\\')
@@ -2469,6 +2791,7 @@ for (;; ptr++)
           else inescq = TRUE;
           continue;
           }
+        else if (-c == ESC_E) continue;  /* Ignore orphan \E */
 
         if (c < 0)
           {
@@ -2517,6 +2840,133 @@ for (;; ptr++)
           else if (c == -ESC_d || c == -ESC_D || c == -ESC_w ||
                    c == -ESC_W || c == -ESC_s || c == -ESC_S) continue;
 
+          /* We need to deal with \H, \h, \V, and \v in both phases because
+          they use extra memory. */
+
+          if (-c == ESC_h)
+            {
+            SETBIT(classbits, 0x09); /* VT */
+            SETBIT(classbits, 0x20); /* SPACE */
+            SETBIT(classbits, 0xa0); /* NSBP */
+#ifdef SUPPORT_UTF8
+            if (utf8)
+              {
+              class_utf8 = TRUE;
+              *class_utf8data++ = XCL_SINGLE;
+              class_utf8data += _pcre_ord2utf8(0x1680, class_utf8data);
+              *class_utf8data++ = XCL_SINGLE;
+              class_utf8data += _pcre_ord2utf8(0x180e, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x2000, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x200A, class_utf8data);
+              *class_utf8data++ = XCL_SINGLE;
+              class_utf8data += _pcre_ord2utf8(0x202f, class_utf8data);
+              *class_utf8data++ = XCL_SINGLE;
+              class_utf8data += _pcre_ord2utf8(0x205f, class_utf8data);
+              *class_utf8data++ = XCL_SINGLE;
+              class_utf8data += _pcre_ord2utf8(0x3000, class_utf8data);
+              }
+#endif
+            continue;
+            }
+
+          if (-c == ESC_H)
+            {
+            for (c = 0; c < 32; c++)
+              {
+              int x = 0xff;
+              switch (c)
+                {
+                case 0x09/8: x ^= 1 << (0x09%8); break;
+                case 0x20/8: x ^= 1 << (0x20%8); break;
+                case 0xa0/8: x ^= 1 << (0xa0%8); break;
+                default: break;
+                }
+              classbits[c] |= x;
+              }
+
+#ifdef SUPPORT_UTF8
+            if (utf8)
+              {
+              class_utf8 = TRUE;
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x167f, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x1681, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x180d, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x180f, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x1fff, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x200B, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x202e, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x2030, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x205e, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x2060, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x2fff, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x3001, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data);
+              }
+#endif
+            continue;
+            }
+
+          if (-c == ESC_v)
+            {
+            SETBIT(classbits, 0x0a); /* LF */
+            SETBIT(classbits, 0x0b); /* VT */
+            SETBIT(classbits, 0x0c); /* FF */
+            SETBIT(classbits, 0x0d); /* CR */
+            SETBIT(classbits, 0x85); /* NEL */
+#ifdef SUPPORT_UTF8
+            if (utf8)
+              {
+              class_utf8 = TRUE;
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x2028, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data);
+              }
+#endif
+            continue;
+            }
+
+          if (-c == ESC_V)
+            {
+            for (c = 0; c < 32; c++)
+              {
+              int x = 0xff;
+              switch (c)
+                {
+                case 0x0a/8: x ^= 1 << (0x0a%8);
+                             x ^= 1 << (0x0b%8);
+                             x ^= 1 << (0x0c%8);
+                             x ^= 1 << (0x0d%8);
+                             break;
+                case 0x85/8: x ^= 1 << (0x85%8); break;
+                default: break;
+                }
+              classbits[c] |= x;
+              }
+
+#ifdef SUPPORT_UTF8
+            if (utf8)
+              {
+              class_utf8 = TRUE;
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x2027, class_utf8data);
+              *class_utf8data++ = XCL_RANGE;
+              class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data);
+              class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data);
+              }
+#endif
+            continue;
+            }
+
           /* We need to deal with \P and \p in both phases. */
 
 #ifdef SUPPORT_UCP
@@ -2568,6 +3018,12 @@ for (;; ptr++)
 
       oldptr = ptr;
 
+      /* Remember \r or \n */
+
+      if (c == '\r' || c == '\n') cd->external_flags |= PCRE_HASCRORLF;
+
+      /* Check for range */
+
       if (!inescq && ptr[1] == '-')
         {
         int d;
@@ -2635,6 +3091,10 @@ for (;; ptr++)
 
         if (d == c) goto LONE_SINGLE_CHARACTER;  /* A few lines below */
 
+        /* Remember \r or \n */
+
+        if (d == '\r' || d == '\n') cd->external_flags |= PCRE_HASCRORLF;
+
         /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless
         matching, we have to use an XCLASS with extra data items. Caseless
         matching for characters > 127 is available only if UCP support is
@@ -2657,14 +3117,18 @@ for (;; ptr++)
             unsigned int origd = d;
             while (get_othercase_range(&cc, origd, &occ, &ocd))
               {
-              if (occ >= c && ocd <= d) continue;  /* Skip embedded ranges */
+              if (occ >= (unsigned int)c &&
+                  ocd <= (unsigned int)d)
+                continue;                          /* Skip embedded ranges */
 
-              if (occ < c  && ocd >= c - 1)        /* Extend the basic range */
+              if (occ < (unsigned int)c  &&
+                  ocd >= (unsigned int)c - 1)      /* Extend the basic range */
                 {                                  /* if there is overlap,   */
                 c = occ;                           /* noting that if occ < c */
                 continue;                          /* we can't have ocd > d  */
                 }                                  /* because a subrange is  */
-              if (ocd > d && occ <= d + 1)         /* always shorter than    */
+              if (ocd > (unsigned int)d &&
+                  occ <= (unsigned int)d + 1)      /* always shorter than    */
                 {                                  /* the basic range.       */
                 d = ocd;
                 continue;
@@ -2784,12 +3248,34 @@ for (;; ptr++)
       goto FAILED;
       }
 
+
+/* This code has been disabled because it would mean that \s counts as
+an explicit \r or \n reference, and that's not really what is wanted. Now
+we set the flag only if there is a literal "\r" or "\n" in the class. */
+
+#if 0
+    /* Remember whether \r or \n are in this class */
+
+    if (negate_class)
+      {
+      if ((classbits[1] & 0x24) != 0x24) cd->external_flags |= PCRE_HASCRORLF;
+      }
+    else
+      {
+      if ((classbits[1] & 0x24) != 0) cd->external_flags |= PCRE_HASCRORLF;
+      }
+#endif
+
+
     /* If class_charcount is 1, we saw precisely one character whose value is
-    less than 256. In non-UTF-8 mode we can always optimize. In UTF-8 mode, we
-    can optimize the negative case only if there were no characters >= 128
-    because OP_NOT and the related opcodes like OP_NOTSTAR operate on
-    single-bytes only. This is an historical hangover. Maybe one day we can
-    tidy these opcodes to handle multi-byte characters.
+    less than 256. As long as there were no characters >= 128 and there was no
+    use of \p or \P, in other words, no use of any XCLASS features, we can
+    optimize.
+
+    In UTF-8 mode, we can optimize the negative case only if there were no
+    characters >= 128 because OP_NOT and the related opcodes like OP_NOTSTAR
+    operate on single-bytes only. This is an historical hangover. Maybe one day
+    we can tidy these opcodes to handle multi-byte characters.
 
     The optimization throws away the bit map. We turn the item into a
     1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note
@@ -2799,10 +3285,8 @@ for (;; ptr++)
     reqbyte, save the previous value for reinstating. */
 
 #ifdef SUPPORT_UTF8
-    if (class_charcount == 1 &&
-          (!utf8 ||
-          (!class_utf8 && (!negate_class || class_lastchar < 128))))
-
+    if (class_charcount == 1 && !class_utf8 &&
+      (!utf8 || !negate_class || class_lastchar < 128))
 #else
     if (class_charcount == 1)
 #endif
@@ -3074,7 +3558,7 @@ for (;; ptr++)
       /* All real repeats make it impossible to handle partial matching (maybe
       one day we will be able to remove this restriction). */
 
-      if (repeat_max != 1) cd->nopartial = TRUE;
+      if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL;
 
       /* Combine the op_type with the repeat_type */
 
@@ -3224,7 +3708,7 @@ for (;; ptr++)
       /* All real repeats make it impossible to handle partial matching (maybe
       one day we will be able to remove this restriction). */
 
-      if (repeat_max != 1) cd->nopartial = TRUE;
+      if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL;
 
       if (repeat_min == 0 && repeat_max == -1)
         *code++ = OP_CRSTAR + repeat_type;
@@ -3260,14 +3744,6 @@ for (;; ptr++)
         goto FAILED;
         }
 
-      /* This is a paranoid check to stop integer overflow later on */
-
-      if (len > MAX_DUPLENGTH)
-        {
-        *errorcodeptr = ERR50;
-        goto FAILED;
-        }
-
       /* If the maximum repeat count is unlimited, find the end of the bracket
       by scanning through from the start, and compute the offset back to it
       from the current code pointer. There may be an OP_OPT setting following
@@ -3356,10 +3832,21 @@ for (;; ptr++)
         if (repeat_min > 1)
           {
           /* In the pre-compile phase, we don't actually do the replication. We
-          just adjust the length as if we had. */
+          just adjust the length as if we had. Do some paranoid checks for
+          potential integer overflow. */
 
           if (lengthptr != NULL)
-            *lengthptr += (repeat_min - 1)*length_prevgroup;
+            {
+            int delta = (repeat_min - 1)*length_prevgroup;
+            if ((double)(repeat_min - 1)*(double)length_prevgroup >
+                                                            (double)INT_MAX ||
+                OFLOW_MAX - *lengthptr < delta)
+              {
+              *errorcodeptr = ERR20;
+              goto FAILED;
+              }
+            *lengthptr += delta;
+            }
 
           /* This is compiling for real */
 
@@ -3397,11 +3884,23 @@ for (;; ptr++)
         /* In the pre-compile phase, we don't actually do the replication. We
         just adjust the length as if we had. For each repetition we must add 1
         to the length for BRAZERO and for all but the last repetition we must
-        add 2 + 2*LINKSIZE to allow for the nesting that occurs. */
+        add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some
+        paranoid checks to avoid integer overflow. */
 
         if (lengthptr != NULL && repeat_max > 0)
-          *lengthptr += repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) -
-            2 - 2*LINK_SIZE;  /* Last one doesn't nest */
+          {
+          int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) -
+                      2 - 2*LINK_SIZE;   /* Last one doesn't nest */
+          if ((double)repeat_max *
+                (double)(length_prevgroup + 1 + 2 + 2*LINK_SIZE)
+                  > (double)INT_MAX ||
+              OFLOW_MAX - *lengthptr < delta)
+            {
+            *errorcodeptr = ERR20;
+            goto FAILED;
+            }
+          *lengthptr += delta;
+          }
 
         /* This is compiling for real */
 
@@ -3553,17 +4052,55 @@ for (;; ptr++)
     /* ===================================================================*/
     /* Start of nested parenthesized sub-expression, or comment or lookahead or
     lookbehind or option setting or condition or all the other extended
-    parenthesis forms. First deal with the specials; all are introduced by ?,
-    and the appearance of any of them means that this is not a capturing
-    group. */
+    parenthesis forms.  */
 
     case '(':
     newoptions = options;
     skipbytes = 0;
     bravalue = OP_CBRA;
     save_hwm = cd->hwm;
+    reset_bracount = FALSE;
+
+    /* First deal with various "verbs" that can be introduced by '*'. */
+
+    if (*(++ptr) == '*' && (cd->ctypes[ptr[1]] & ctype_letter) != 0)
+      {
+      int i, namelen;
+      const char *vn = verbnames;
+      const uschar *name = ++ptr;
+      previous = NULL;
+      while ((cd->ctypes[*++ptr] & ctype_letter) != 0);
+      if (*ptr == ':')
+        {
+        *errorcodeptr = ERR59;   /* Not supported */
+        goto FAILED;
+        }
+      if (*ptr != ')')
+        {
+        *errorcodeptr = ERR60;
+        goto FAILED;
+        }
+      namelen = ptr - name;
+      for (i = 0; i < verbcount; i++)
+        {
+        if (namelen == verbs[i].len &&
+            strncmp((char *)name, vn, namelen) == 0)
+          {
+          *code = verbs[i].op;
+          if (*code++ == OP_ACCEPT) cd->had_accept = TRUE;
+          break;
+          }
+        vn += verbs[i].len + 1;
+        }
+      if (i < verbcount) continue;
+      *errorcodeptr = ERR60;
+      goto FAILED;
+      }
 
-    if (*(++ptr) == '?')
+    /* Deal with the extended parentheses; all are introduced by '?', and the
+    appearance of any of them means that this is not a capturing group. */
+
+    else if (*ptr == '?')
       {
       int i, set, unset, namelen;
       int *optset;
@@ -3583,6 +4120,11 @@ for (;; ptr++)
         continue;
 
 
+        /* ------------------------------------------------------------ */
+        case '|':                 /* Reset capture count for each branch */
+        reset_bracount = TRUE;
+        /* Fall through */
+
         /* ------------------------------------------------------------ */
         case ':':                 /* Non-capturing bracket */
         bravalue = OP_BRA;
@@ -3619,6 +4161,7 @@ for (;; ptr++)
 
         code[1+LINK_SIZE] = OP_CREF;
         skipbytes = 3;
+        refsign = -1;
 
         /* Check for a test for recursion in a named group. */
 
@@ -3642,7 +4185,11 @@ for (;; ptr++)
           terminator = '\'';
           ptr++;
           }
-        else terminator = 0;
+        else
+          {
+          terminator = 0;
+          if (ptr[1] == '-' || ptr[1] == '+') refsign = *(++ptr);
+          }
 
         /* We now expect to read a name; any thing else is an error */
 
@@ -3678,7 +4225,32 @@ for (;; ptr++)
         if (lengthptr != NULL) break;
 
         /* In the real compile we do the work of looking for the actual
-        reference. */
+        reference. If the string started with "+" or "-" we require the rest to
+        be digits, in which case recno will be set. */
+
+        if (refsign > 0)
+          {
+          if (recno <= 0)
+            {
+            *errorcodeptr = ERR58;
+            goto FAILED;
+            }
+          if (refsign == '-')
+            {
+            recno = cd->bracount - recno + 1;
+            if (recno <= 0)
+              {
+              *errorcodeptr = ERR15;
+              goto FAILED;
+              }
+            }
+          else recno += cd->bracount;
+          PUT2(code, 2+LINK_SIZE, recno);
+          break;
+          }
+
+        /* Otherwise (did not start with "+" or "-"), start by looking for the
+        name. */
 
         slot = cd->name_table;
         for (i = 0; i < cd->names_found; i++)
@@ -3770,8 +4342,14 @@ for (;; ptr++)
 
         /* ------------------------------------------------------------ */
         case '!':                 /* Negative lookahead */
-        bravalue = OP_ASSERT_NOT;
         ptr++;
+        if (*ptr == ')')          /* Optimize (?!) */
+          {
+          *code++ = OP_FAIL;
+          previous = NULL;
+          continue;
+          }
+        bravalue = OP_ASSERT_NOT;
         break;
 
 
@@ -3997,19 +4575,54 @@ for (;; ptr++)
 
 
         /* ------------------------------------------------------------ */
+        case '-': case '+':
         case '0': case '1': case '2': case '3': case '4':   /* Recursion or */
         case '5': case '6': case '7': case '8': case '9':   /* subroutine */
           {
           const uschar *called;
+
+          if ((refsign = *ptr) == '+') ptr++;
+          else if (refsign == '-')
+            {
+            if ((digitab[ptr[1]] & ctype_digit) == 0)
+              goto OTHER_CHAR_AFTER_QUERY;
+            ptr++;
+            }
+
           recno = 0;
           while((digitab[*ptr] & ctype_digit) != 0)
             recno = recno * 10 + *ptr++ - '0';
+
           if (*ptr != ')')
             {
             *errorcodeptr = ERR29;
             goto FAILED;
             }
 
+          if (refsign == '-')
+            {
+            if (recno == 0)
+              {
+              *errorcodeptr = ERR58;
+              goto FAILED;
+              }
+            recno = cd->bracount - recno + 1;
+            if (recno <= 0)
+              {
+              *errorcodeptr = ERR15;
+              goto FAILED;
+              }
+            }
+          else if (refsign == '+')
+            {
+            if (recno == 0)
+              {
+              *errorcodeptr = ERR58;
+              goto FAILED;
+              }
+            recno += cd->bracount;
+            }
+
           /* Come here from code above that handles a named recursion */
 
           HANDLE_RECURSION:
@@ -4082,6 +4695,7 @@ for (;; ptr++)
 
         /* ------------------------------------------------------------ */
         default:              /* Other characters: check option setting */
+        OTHER_CHAR_AFTER_QUERY:
         set = unset = 0;
         optset = &set;
 
@@ -4093,7 +4707,7 @@ for (;; ptr++)
 
             case 'J':    /* Record that it changed in the external options */
             *optset |= PCRE_DUPNAMES;
-            cd->external_options |= PCRE_JCHANGED;
+            cd->external_flags |= PCRE_JCHANGED;
             break;
 
             case 'i': *optset |= PCRE_CASELESS; break;
@@ -4216,6 +4830,7 @@ for (;; ptr++)
          errorcodeptr,                 /* Where to put an error message */
          (bravalue == OP_ASSERTBACK ||
           bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
+         reset_bracount,               /* True if (?| group */
          skipbytes,                    /* Skip over bracket number */
          &subfirstbyte,                /* For possible first char */
          &subreqbyte,                  /* For possible last char */
@@ -4232,9 +4847,11 @@ for (;; ptr++)
     is on the bracket. */
 
     /* If this is a conditional bracket, check that there are no more than
-    two branches in the group, or just one if it's a DEFINE group. */
+    two branches in the group, or just one if it's a DEFINE group. We do this
+    in the real compile phase, not in the pre-pass, where the whole group may
+    not be available. */
 
-    if (bravalue == OP_COND)
+    if (bravalue == OP_COND && lengthptr == NULL)
       {
       uschar *tc = code;
       int condcount = 0;
@@ -4281,23 +4898,29 @@ for (;; ptr++)
       goto FAILED;
       }
 
-    /* In the pre-compile phase, update the length by the length of the nested
-    group, less the brackets at either end. Then reduce the compiled code to
-    just the brackets so that it doesn't use much memory if it is duplicated by
-    a quantifier. */
+    /* In the pre-compile phase, update the length by the length of the group,
+    less the brackets at either end. Then reduce the compiled code to just a
+    set of non-capturing brackets so that it doesn't use much memory if it is
+    duplicated by a quantifier.*/
 
     if (lengthptr != NULL)
       {
+      if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)
+        {
+        *errorcodeptr = ERR20;
+        goto FAILED;
+        }
       *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;
-      code++;
+      *code++ = OP_BRA;
       PUTINC(code, 0, 1 + LINK_SIZE);
       *code++ = OP_KET;
       PUTINC(code, 0, 1 + LINK_SIZE);
+      break;    /* No need to waste time with special character handling */
       }
 
     /* Otherwise update the main code pointer to the end of the group. */
 
-    else code = tempcode;
+    code = tempcode;
 
     /* For a DEFINE group, required and first character settings are not
     relevant. */
@@ -4394,12 +5017,13 @@ for (;; ptr++)
       zerofirstbyte = firstbyte;
       zeroreqbyte = reqbyte;
 
-      /* \k<name> or \k'name' is a back reference by name (Perl syntax) */
+      /* \k<name> or \k'name' is a back reference by name (Perl syntax).
+      We also support \k{name} (.NET syntax) */
 
-      if (-c == ESC_k && (ptr[1] == '<' || ptr[1] == '\''))
+      if (-c == ESC_k && (ptr[1] == '<' || ptr[1] == '\'' || ptr[1] == '{'))
         {
         is_recurse = FALSE;
-        terminator = (*(++ptr) == '<')? '>' : '\'';
+        terminator = (*(++ptr) == '<')? '>' : (*ptr == '\'')? '\'' : '}';
         goto NAMED_REF_OR_RECURSE;
         }
 
@@ -4500,6 +5124,11 @@ for (;; ptr++)
     *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARNC : OP_CHAR;
     for (c = 0; c < mclength; c++) *code++ = mcbuffer[c];
 
+    /* Remember if \r or \n were seen */
+
+    if (mcbuffer[0] == '\r' || mcbuffer[0] == '\n')
+      cd->external_flags |= PCRE_HASCRORLF;
+
     /* Set the first and required bytes appropriately. If no previous first
     byte, set it from this character, but revert to none on a zero repeat.
     Otherwise, leave the firstbyte value alone, and don't change it on a zero
@@ -4565,13 +5194,14 @@ This function is used during the pre-compile phase when we are trying to find
 out the amount of memory needed, as well as during the real compile phase. The
 value of lengthptr distinguishes the two phases.
 
-Argument:
+Arguments:
   options        option bits, including any changes for this subpattern
   oldims         previous settings of ims option bits
   codeptr        -> the address of the current code pointer
   ptrptr         -> the address of the current pattern pointer
   errorcodeptr   -> pointer to error code variable
   lookbehind     TRUE if this is a lookbehind assertion
+  reset_bracount TRUE to reset the count for each branch
   skipbytes      skip this many bytes at start (for brackets and OP_COND)
   firstbyteptr   place to put the first required character, or a negative number
   reqbyteptr     place to put the last required character, or a negative number
@@ -4585,8 +5215,9 @@ Returns:         TRUE on success
 
 static BOOL
 compile_regex(int options, int oldims, uschar **codeptr, const uschar **ptrptr,
-  int *errorcodeptr, BOOL lookbehind, int skipbytes, int *firstbyteptr,
-  int *reqbyteptr, branch_chain *bcptr, compile_data *cd, int *lengthptr)
+  int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes,
+  int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd,
+  int *lengthptr)
 {
 const uschar *ptr = *ptrptr;
 uschar *code = *codeptr;
@@ -4596,6 +5227,8 @@ uschar *reverse_count = NULL;
 int firstbyte, reqbyte;
 int branchfirstbyte, branchreqbyte;
 int length;
+int orig_bracount;
+int max_bracount;
 branch_chain bc;
 
 bc.outer = bcptr;
@@ -4624,8 +5257,14 @@ code += 1 + LINK_SIZE + skipbytes;
 
 /* Loop for each alternative branch */
 
+orig_bracount = max_bracount = cd->bracount;
 for (;;)
   {
+  /* For a (?| group, reset the capturing bracket count so that each branch
+  uses the same numbers. */
+
+  if (reset_bracount) cd->bracount = orig_bracount;
+
   /* Handle a change of ims options at the start of the branch */
 
   if ((options & PCRE_IMS) != oldims)
@@ -4655,6 +5294,11 @@ for (;;)
     return FALSE;
     }
 
+  /* Keep the highest bracket count in case (?| was used and some branch
+  has fewer than the rest. */
+
+  if (cd->bracount > max_bracount) max_bracount = cd->bracount;
+
   /* In the real compile phase, there is some post-processing to be done. */
 
   if (lengthptr == NULL)
@@ -4718,26 +5362,29 @@ for (;;)
       }
     }
 
-  /* Reached end of expression, either ')' or end of pattern. Go back through
-  the alternative branches and reverse the chain of offsets, with the field in
-  the BRA item now becoming an offset to the first alternative. If there are
-  no alternatives, it points to the end of the group. The length in the
-  terminating ket is always the length of the whole bracketed item. If any of
-  the ims options were changed inside the group, compile a resetting op-code
-  following, except at the very end of the pattern. Return leaving the pointer
-  at the terminating char. */
+  /* Reached end of expression, either ')' or end of pattern. In the real
+  compile phase, go back through the alternative branches and reverse the chain
+  of offsets, with the field in the BRA item now becoming an offset to the
+  first alternative. If there are no alternatives, it points to the end of the
+  group. The length in the terminating ket is always the length of the whole
+  bracketed item. If any of the ims options were changed inside the group,
+  compile a resetting op-code following, except at the very end of the pattern.
+  Return leaving the pointer at the terminating char. */
 
   if (*ptr != '|')
     {
-    int branch_length = code - last_branch;
-    do
+    if (lengthptr == NULL)
       {
-      int prev_length = GET(last_branch, 1);
-      PUT(last_branch, 1, branch_length);
-      branch_length = prev_length;
-      last_branch -= branch_length;
+      int branch_length = code - last_branch;
+      do
+        {
+        int prev_length = GET(last_branch, 1);
+        PUT(last_branch, 1, branch_length);
+        branch_length = prev_length;
+        last_branch -= branch_length;
+        }
+      while (branch_length > 0);
       }
-    while (branch_length > 0);
 
     /* Fill in the ket */
 
@@ -4754,27 +5401,51 @@ for (;;)
       length += 2;
       }
 
+    /* Retain the highest bracket number, in case resetting was used. */
+
+    cd->bracount = max_bracount;
+
     /* Set values to pass back */
 
     *codeptr = code;
     *ptrptr = ptr;
     *firstbyteptr = firstbyte;
     *reqbyteptr = reqbyte;
-    if (lengthptr != NULL) *lengthptr += length;
+    if (lengthptr != NULL)
+      {
+      if (OFLOW_MAX - *lengthptr < length)
+        {
+        *errorcodeptr = ERR20;
+        return FALSE;
+        }
+      *lengthptr += length;
+      }
     return TRUE;
     }
 
-  /* Another branch follows; insert an "or" node. Its length field points back
+  /* Another branch follows. In the pre-compile phase, we can move the code
+  pointer back to where it was for the start of the first branch. (That is,
+  pretend that each branch is the only one.)
+
+  In the real compile phase, insert an ALT node. Its length field points back
   to the previous branch while the bracket remains open. At the end the chain
   is reversed. It's done like this so that the start of the bracket has a
   zero offset until it is closed, making it possible to detect recursion. */
 
-  *code = OP_ALT;
-  PUT(code, 1, code - last_branch);
-  bc.current = last_branch = code;
-  code += 1 + LINK_SIZE;
+  if (lengthptr != NULL)
+    {
+    code = *codeptr + 1 + LINK_SIZE + skipbytes;
+    length += 1 + LINK_SIZE;
+    }
+  else
+    {
+    *code = OP_ALT;
+    PUT(code, 1, code - last_branch);
+    bc.current = last_branch = code;
+    code += 1 + LINK_SIZE;
+    }
+
   ptr++;
-  length += 1 + LINK_SIZE;
   }
 /* Control never reaches here */
 }
@@ -5041,7 +5712,7 @@ Returns:        pointer to compiled data block, or NULL on error,
                 with errorptr and erroroffset set
 */
 
-PCRE_DATA_SCOPE pcre *
+PCRE_EXP_DEFN pcre *
 pcre_compile(const char *pattern, int options, const char **errorptr,
   int *erroroffset, const unsigned char *tables)
 {
@@ -5049,7 +5720,7 @@ return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
 }
 
 
-PCRE_DATA_SCOPE pcre *
+PCRE_EXP_DEFN pcre *
 pcre_compile2(const char *pattern, int options, int *errorcodeptr,
   const char **errorptr, int *erroroffset, const unsigned char *tables)
 {
@@ -5057,6 +5728,7 @@ real_pcre *re;
 int length = 1;  /* For final END opcode */
 int firstbyte, reqbyte, newline;
 int errorcode = 0;
+int skipatstart = 0;
 #ifdef SUPPORT_UTF8
 BOOL utf8;
 #endif
@@ -5098,7 +5770,7 @@ if (errorcodeptr != NULL) *errorcodeptr = ERR0;
 if (erroroffset == NULL)
   {
   errorcode = ERR16;
-  goto PCRE_EARLY_ERROR_RETURN;
+  goto PCRE_EARLY_ERROR_RETURN2;
   }
 
 *erroroffset = 0;
@@ -5111,7 +5783,7 @@ if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 &&
      (*erroroffset = _pcre_valid_utf8((uschar *)pattern, -1)) >= 0)
   {
   errorcode = ERR44;
-  goto PCRE_UTF8_ERROR_RETURN;
+  goto PCRE_EARLY_ERROR_RETURN2;
   }
 #else
 if ((options & PCRE_UTF8) != 0)
@@ -5135,21 +5807,69 @@ cd->fcc = tables + fcc_offset;
 cd->cbits = tables + cbits_offset;
 cd->ctypes = tables + ctypes_offset;
 
+/* Check for global one-time settings at the start of the pattern, and remember
+the offset for later. */
+
+while (ptr[skipatstart] == '(' && ptr[skipatstart+1] == '*')
+  {
+  int newnl = 0;
+  int newbsr = 0;
+
+  if (strncmp((char *)(ptr+skipatstart+2), "CR)", 3) == 0)
+    { skipatstart += 5; newnl = PCRE_NEWLINE_CR; }
+  else if (strncmp((char *)(ptr+skipatstart+2), "LF)", 3)  == 0)
+    { skipatstart += 5; newnl = PCRE_NEWLINE_LF; }
+  else if (strncmp((char *)(ptr+skipatstart+2), "CRLF)", 5)  == 0)
+    { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; }
+  else if (strncmp((char *)(ptr+skipatstart+2), "ANY)", 4) == 0)
+    { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; }
+  else if (strncmp((char *)(ptr+skipatstart+2), "ANYCRLF)", 8)  == 0)
+    { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; }
+
+  else if (strncmp((char *)(ptr+skipatstart+2), "BSR_ANYCRLF)", 12) == 0)
+    { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; }
+  else if (strncmp((char *)(ptr+skipatstart+2), "BSR_UNICODE)", 12) == 0)
+    { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; }
+
+  if (newnl != 0)
+    options = (options & ~PCRE_NEWLINE_BITS) | newnl;
+  else if (newbsr != 0)
+    options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr;
+  else break;
+  }
+
+/* Check validity of \R options. */
+
+switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
+  {
+  case 0:
+  case PCRE_BSR_ANYCRLF:
+  case PCRE_BSR_UNICODE:
+  break;
+  default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN;
+  }
+
 /* Handle different types of newline. The three bits give seven cases. The
-current code allows for fixed one- or two-byte sequences, plus "any". */
+current code allows for fixed one- or two-byte sequences, plus "any" and
+"anycrlf". */
 
-switch (options & (PCRE_NEWLINE_CRLF | PCRE_NEWLINE_ANY))
+switch (options & PCRE_NEWLINE_BITS)
   {
-  case 0: newline = NEWLINE; break;   /* Compile-time default */
+  case 0: newline = NEWLINE; break;   /* Build-time default */
   case PCRE_NEWLINE_CR: newline = '\r'; break;
   case PCRE_NEWLINE_LF: newline = '\n'; break;
   case PCRE_NEWLINE_CR+
        PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;
   case PCRE_NEWLINE_ANY: newline = -1; break;
+  case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
   default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN;
   }
 
-if (newline < 0)
+if (newline == -2)
+  {
+  cd->nltype = NLTYPE_ANYCRLF;
+  }
+else if (newline < 0)
   {
   cd->nltype = NLTYPE_ANY;
   }
@@ -5198,8 +5918,8 @@ cd->hwm = cworkspace;
 cd->start_pattern = (const uschar *)pattern;
 cd->end_pattern = (const uschar *)(pattern + strlen(pattern));
 cd->req_varyopt = 0;
-cd->nopartial = FALSE;
 cd->external_options = options;
+cd->external_flags = 0;
 
 /* Now do the pre-compile. On error, errorcode will be set non-zero, so we
 don't need to look at the result of the function here. The initial options have
@@ -5207,10 +5927,12 @@ been put into the cd block so that they can be changed if an option setting is
 found within the regex right at the beginning. Bringing initial option settings
 outside can help speed up starting point checks. */
 
+ptr += skipatstart;
 code = cworkspace;
 *code = OP_BRA;
 (void)compile_regex(cd->external_options, cd->external_options & PCRE_IMS,
-  &code, &ptr, &errorcode, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, &length);
+  &code, &ptr, &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd,
+  &length);
 if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;
 
 DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
@@ -5236,14 +5958,16 @@ if (re == NULL)
   goto PCRE_EARLY_ERROR_RETURN;
   }
 
-/* Put in the magic number, and save the sizes, initial options, and character
-table pointer. NULL is used for the default character tables. The nullpad field
-is at the end; it's there to help in the case when a regex compiled on a system
-with 4-byte pointers is run on another with 8-byte pointers. */
+/* Put in the magic number, and save the sizes, initial options, internal
+flags, and character table pointer. NULL is used for the default character
+tables. The nullpad field is at the end; it's there to help in the case when a
+regex compiled on a system with 4-byte pointers is run on another with 8-byte
+pointers. */
 
 re->magic_number = MAGIC_NUMBER;
 re->size = size;
 re->options = cd->external_options;
+re->flags = cd->external_flags;
 re->dummy1 = 0;
 re->first_byte = 0;
 re->req_byte = 0;
@@ -5268,21 +5992,22 @@ codestart = cd->name_table + re->name_entry_size * re->name_count;
 cd->start_code = codestart;
 cd->hwm = cworkspace;
 cd->req_varyopt = 0;
-cd->nopartial = FALSE;
+cd->had_accept = FALSE;
 
 /* Set up a starting, non-extracting bracket, then compile the expression. On
 error, errorcode will be set non-zero, so we don't need to look at the result
 of the function here. */
 
-ptr = (const uschar *)pattern;
+ptr = (const uschar *)pattern + skipatstart;
 code = (uschar *)codestart;
 *code = OP_BRA;
 (void)compile_regex(re->options, re->options & PCRE_IMS, &code, &ptr,
-  &errorcode, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, NULL);
+  &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, NULL);
 re->top_bracket = cd->bracount;
 re->top_backref = cd->top_backref;
+re->flags = cd->external_flags;
 
-if (cd->nopartial) re->options |= PCRE_NOPARTIAL;
+if (cd->had_accept) reqbyte = -1;   /* Must disable after (*ACCEPT) */
 
 /* If not reached end of pattern on success, there's an excess bracket. */
 
@@ -5323,10 +6048,8 @@ if (errorcode != 0)
   (pcre_free)(re);
   PCRE_EARLY_ERROR_RETURN:
   *erroroffset = ptr - (const uschar *)pattern;
-#ifdef SUPPORT_UTF8
-  PCRE_UTF8_ERROR_RETURN:
-#endif
-  *errorptr = error_texts[errorcode];
+  PCRE_EARLY_ERROR_RETURN2:
+  *errorptr = find_error_text(errorcode);
   if (errorcodeptr != NULL) *errorcodeptr = errorcode;
   return NULL;
   }
@@ -5355,10 +6078,10 @@ if ((re->options & PCRE_ANCHORED) == 0)
       int ch = firstbyte & 255;
       re->first_byte = ((firstbyte & REQ_CASELESS) != 0 &&
          cd->fcc[ch] == ch)? ch : firstbyte;
-      re->options |= PCRE_FIRSTSET;
+      re->flags |= PCRE_FIRSTSET;
       }
     else if (is_startline(codestart, 0, cd->backref_map))
-      re->options |= PCRE_STARTLINE;
+      re->flags |= PCRE_STARTLINE;
     }
   }
 
@@ -5372,7 +6095,7 @@ if (reqbyte >= 0 &&
   int ch = reqbyte & 255;
   re->req_byte = ((reqbyte & REQ_CASELESS) != 0 &&
     cd->fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte;
-  re->options |= PCRE_REQCHSET;
+  re->flags |= PCRE_REQCHSET;
   }
 
 /* Print out the compiled data if debugging is enabled. This is never the
@@ -5383,21 +6106,9 @@ case when building a production library. */
 printf("Length = %d top_bracket = %d top_backref = %d\n",
   length, re->top_bracket, re->top_backref);
 
-if (re->options != 0)
-  {
-  printf("%s%s%s%s%s%s%s%s%s\n",
-    ((re->options & PCRE_NOPARTIAL) != 0)? "nopartial " : "",
-    ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "",
-    ((re->options & PCRE_CASELESS) != 0)? "caseless " : "",
-    ((re->options & PCRE_EXTENDED) != 0)? "extended " : "",
-    ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "",
-    ((re->options & PCRE_DOTALL) != 0)? "dotall " : "",
-    ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "",
-    ((re->options & PCRE_EXTRA) != 0)? "extra " : "",
-    ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : "");
-  }
+printf("Options=%08x\n", re->options);
 
-if ((re->options & PCRE_FIRSTSET) != 0)
+if ((re->flags & PCRE_FIRSTSET) != 0)
   {
   int ch = re->first_byte & 255;
   const char *caseless = ((re->first_byte & REQ_CASELESS) == 0)?
@@ -5406,7 +6117,7 @@ if ((re->options & PCRE_FIRSTSET) != 0)
     else printf("First char = \\x%02x%s\n", ch, caseless);
   }
 
-if ((re->options & PCRE_REQCHSET) != 0)
+if ((re->flags & PCRE_REQCHSET) != 0)
   {
   int ch = re->req_byte & 255;
   const char *caseless = ((re->req_byte & REQ_CASELESS) == 0)?
@@ -5415,7 +6126,7 @@ if ((re->options & PCRE_REQCHSET) != 0)
     else printf("Req char = \\x%02x%s\n", ch, caseless);
   }
 
-pcre_printint(re, stdout);
+pcre_printint(re, stdout, TRUE);
 
 /* This check is done here in the debugging case so that the code that
 was compiled can be seen. */
@@ -5423,7 +6134,7 @@ was compiled can be seen. */
 if (code - codestart > length)
   {
   (pcre_free)(re);
-  *errorptr = error_texts[ERR23];
+  *errorptr = find_error_text(ERR23);
   *erroroffset = ptr - (uschar *)pattern;
   if (errorcodeptr != NULL) *errorcodeptr = ERR23;
   return NULL;