]> granicus.if.org Git - php/commitdiff
MFH: Upgraded bundled PCRE to version 8.10.
authorIlia Alshanetsky <iliaa@php.net>
Sat, 14 Aug 2010 14:37:13 +0000 (14:37 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Sat, 14 Aug 2010 14:37:13 +0000 (14:37 +0000)
27 files changed:
NEWS
ext/pcre/pcrelib/ChangeLog
ext/pcre/pcrelib/NEWS
ext/pcre/pcrelib/NON-UNIX-USE
ext/pcre/pcrelib/config.h
ext/pcre/pcrelib/doc/pcre.txt
ext/pcre/pcrelib/pcre.h
ext/pcre/pcrelib/pcre_chartables.c
ext/pcre/pcrelib/pcre_compile.c
ext/pcre/pcrelib/pcre_exec.c
ext/pcre/pcrelib/pcre_internal.h
ext/pcre/pcrelib/pcre_printint.src
ext/pcre/pcrelib/pcre_study.c
ext/pcre/pcrelib/pcre_tables.c
ext/pcre/pcrelib/pcre_xclass.c
ext/pcre/pcrelib/pcreposix.c
ext/pcre/pcrelib/pcreposix.h
ext/pcre/pcrelib/testdata/testinput10
ext/pcre/pcrelib/testdata/testinput2
ext/pcre/pcrelib/testdata/testinput5
ext/pcre/pcrelib/testdata/testinput6
ext/pcre/pcrelib/testdata/testinput9
ext/pcre/pcrelib/testdata/testoutput10
ext/pcre/pcrelib/testdata/testoutput2
ext/pcre/pcrelib/testdata/testoutput5
ext/pcre/pcrelib/testdata/testoutput6
ext/pcre/pcrelib/testdata/testoutput9

diff --git a/NEWS b/NEWS
index a189d7019d16d580fb452883049f8125404a195c..c183925ab2674f11ed839ffe5f1dc40839ccaf58 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2010, PHP 5.3.4
+- Upgraded bundled PCRE to version 8.10. (Ilia)
+
 - Changed deprecated ini options on startup from E_WARNING to E_DEPRECATED. 
   (Kalle)
 
index 9e833ee14188c4eca0ef211ee886d8f13f42886b..b2fef0dab72ae31c7a0fc420b0ee8e44ead2edda 100644 (file)
@@ -1,6 +1,101 @@
 ChangeLog for PCRE
 ------------------
 
+Version 8.10 25-Jun-2010
+------------------------
+
+1.  Added support for (*MARK:ARG) and for ARG additions to PRUNE, SKIP, and
+    THEN.
+
+2.  (*ACCEPT) was not working when inside an atomic group.
+
+3.  Inside a character class, \B is treated as a literal by default, but
+    faulted if PCRE_EXTRA is set. This mimics Perl's behaviour (the -w option
+    causes the error). The code is unchanged, but I tidied the documentation.
+
+4.  Inside a character class, PCRE always treated \R and \X as literals,
+    whereas Perl faults them if its -w option is set. I have changed PCRE so
+    that it faults them when PCRE_EXTRA is set.
+
+5.  Added support for \N, which always matches any character other than
+    newline. (It is the same as "." when PCRE_DOTALL is not set.)
+
+6.  When compiling pcregrep with newer versions of gcc which may have
+    FORTIFY_SOURCE set, several warnings "ignoring return value of 'fwrite',
+    declared with attribute warn_unused_result" were given. Just casting the
+    result to (void) does not stop the warnings; a more elaborate fudge is
+    needed. I've used a macro to implement this.
+
+7.  Minor change to pcretest.c to avoid a compiler warning.
+
+8.  Added four artifical Unicode properties to help with an option to make
+    \s etc use properties (see next item). The new properties are: Xan
+    (alphanumeric), Xsp (Perl space), Xps (POSIX space), and Xwd (word).
+
+9.  Added PCRE_UCP to make \b, \d, \s, \w, and certain POSIX character classes
+    use Unicode properties. (*UCP) at the start of a pattern can be used to set
+    this option. Modified pcretest to add /W to test this facility. Added
+    REG_UCP to make it available via the POSIX interface.
+
+10. Added --line-buffered to pcregrep.
+
+11. In UTF-8 mode, if a pattern that was compiled with PCRE_CASELESS was
+    studied, and the match started with a letter with a code point greater than
+    127 whose first byte was different to the first byte of the other case of
+    the letter, the other case of this starting letter was not recognized
+    (#976).
+
+12. If a pattern that was studied started with a repeated Unicode property
+    test, for example, \p{Nd}+, there was the theoretical possibility of
+    setting up an incorrect bitmap of starting bytes, but fortunately it could
+    not have actually happened in practice until change 8 above was made (it
+    added property types that matched character-matching opcodes).
+
+13. pcre_study() now recognizes \h, \v, and \R when constructing a bit map of
+    possible starting bytes for non-anchored patterns.
+
+14. Extended the "auto-possessify" feature of pcre_compile(). It now recognizes
+    \R, and also a number of cases that involve Unicode properties, both
+    explicit and implicit when PCRE_UCP is set.
+
+15. If a repeated Unicode property match (e.g. \p{Lu}*) was used with non-UTF-8
+    input, it could crash or give wrong results if characters with values
+    greater than 0xc0 were present in the subject string. (Detail: it assumed
+    UTF-8 input when processing these items.)
+
+16. Added a lot of (int) casts to avoid compiler warnings in systems where
+    size_t is 64-bit (#991).
+
+17. Added a check for running out of memory when PCRE is compiled with
+    --disable-stack-for-recursion (#990).
+
+18. If the last data line in a file for pcretest does not have a newline on
+    the end, a newline was missing in the output.
+
+19. The default pcre_chartables.c file recognizes only ASCII characters (values
+    less than 128) in its various bitmaps. However, there is a facility for
+    generating tables according to the current locale when PCRE is compiled. It
+    turns out that in some environments, 0x85 and 0xa0, which are Unicode space
+    characters, are recognized by isspace() and therefore were getting set in
+    these tables, and indeed these tables seem to approximate to ISO 8859. This
+    caused a problem in UTF-8 mode when pcre_study() was used to create a list
+    of bytes that can start a match. For \s, it was including 0x85 and 0xa0,
+    which of course cannot start UTF-8 characters. I have changed the code so
+    that only real ASCII characters (less than 128) and the correct starting
+    bytes for UTF-8 encodings are set for characters greater than 127 when in
+    UTF-8 mode. (When PCRE_UCP is set - see 9 above - the code is different
+    altogether.)
+
+20. Added the /T option to pcretest so as to be able to run tests with non-
+    standard character tables, thus making it possible to include the tests
+    used for 19 above in the standard set of tests.
+
+21. A pattern such as (?&t)(?#()(?(DEFINE)(?<t>a)) which has a forward
+    reference to a subpattern the other side of a comment that contains an
+    opening parenthesis caused either an internal compiling error, or a
+    reference to the wrong subpattern.
+
+
 Version 8.02 19-Mar-2010
 ------------------------
 
index 835d03d22fef28e80439390227b31e7fa11f9107..4f21e0bdaf67de51fd3972542fb8b8854a645b7f 100644 (file)
@@ -1,6 +1,17 @@
 News about PCRE releases
 ------------------------
 
+Release 8.10 25-Jun-2010
+------------------------
+
+There are two major additions: support for (*MARK) and friends, and the option
+PCRE_UCP, which changes the behaviour of \b, \d, \s, and \w (and their
+opposites) so that they make use of Unicode properties. There are also a number
+of lesser new features, and several bugs have been fixed. A new option,
+--line-buffered, has been added to pcregrep, for use when it is connected to
+pipes.
+
+
 Release 8.02 19-Mar-2010
 ------------------------
 
index 69668cbb4bb33bc30e727f61c7a901c352e22426..8619b5846445aa415684e7c720cae3a256787636 100644 (file)
@@ -188,9 +188,9 @@ significantly slower when this is done. There is more about stack usage in the
 LINKING PROGRAMS IN WINDOWS ENVIRONMENTS
 
 If you want to statically link a program against a PCRE library in the form of
-a non-dll .a file, you must define PCRE_STATIC before including pcre.h,
-otherwise the pcre_malloc() and pcre_free() exported functions will be declared
-__declspec(dllimport), with unwanted results.
+a non-dll .a file, you must define PCRE_STATIC before including pcre.h or
+pcrecpp.h, otherwise the pcre_malloc() and pcre_free() exported functions will
+be declared __declspec(dllimport), with unwanted results.
 
 
 CALLING CONVENTIONS IN WINDOWS ENVIRONMENTS
@@ -497,5 +497,5 @@ build.log file in the root of the package also.
 
 
 =========================
-Last Updated: 19 January 2010
+Last Updated: 26 May 2010
 ****
index 2e04b29aa7e387166244e0638e4f0f61dc41544c..a3d7e8dae321150d19bb6cfb0c7c525fc76c681e 100644 (file)
@@ -1,10 +1,5 @@
 
 #include <php_compat.h>
-
-#ifndef PHP_WIN32
-# include <php_config.h>
-#endif
-
 #undef PACKAGE_NAME
 #undef PACKAGE_VERSION
 #undef PACKAGE_TARNAME
@@ -23,8 +18,6 @@
 # define PCRE_EXP_DATA_DEFN    __attribute__ ((visibility("default")))
 #endif
 
-/* Exclude these below definitions when building within PHP */
-#ifndef ZEND_API
 
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
@@ -196,9 +189,6 @@ them both to 0; an emulation function will be used. */
 /* Define to 1 if you have `_strtoi64'. */
 /* #undef HAVE__STRTOI64 */
 
-/* Exclude these above definitions when building within PHP */
-#endif
-
 /* The value of LINK_SIZE determines the number of bytes used to store links
    as offsets within the compiled regex. The default is 2, which allows for
    compiled patterns up to 64K long. This covers the vast majority of cases.
@@ -281,13 +271,16 @@ them both to 0; an emulation function will be used. */
 #define PACKAGE_NAME "PCRE"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE 8.02"
+#define PACKAGE_STRING "PCRE 8.10"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "pcre"
 
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "8.02"
+#define PACKAGE_VERSION "8.10"
 
 
 /* If you are compiling for a system other than a Unix-like system or
@@ -343,7 +336,7 @@ them both to 0; an emulation function will be used. */
 
 /* Version number of package */
 #ifndef VERSION
-#define VERSION "8.02"
+#define VERSION "8.10"
 #endif
 
 /* Define to empty if `const' does not conform to ANSI C. */
index aedf8537355910508f58596aed0d6af86372c775..5f6587142590fa25615f0328c11cc13e95406b99 100644 (file)
@@ -26,8 +26,8 @@ INTRODUCTION
        give better JavaScript compatibility.
 
        The  current implementation of PCRE corresponds approximately with Perl
-       5.10, including support for UTF-8 encoded strings and  Unicode  general
-       category  properties.  However,  UTF-8  and  Unicode  support has to be
+       5.10/5.11, including support for UTF-8 encoded strings and Unicode gen-
+       eral  category properties. However, UTF-8 and Unicode support has to be
        explicitly enabled; it is not the default. The  Unicode  tables  corre-
        spond to Unicode release 5.2.0.
 
@@ -222,21 +222,25 @@ UTF-8 AND UNICODE PROPERTY SUPPORT
        not available in the alternative matching function, pcre_dfa_exec().
 
        6.  The  character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly
-       test characters of any code value, but the characters that PCRE  recog-
-       nizes  as  digits,  spaces,  or  word characters remain the same set as
-       before, all with values less than 256. This remains true even when PCRE
-       includes  Unicode  property support, because to do otherwise would slow
-       down PCRE in many common cases. If you really want to test for a  wider
-       sense  of,  say,  "digit",  you must use Unicode property tests such as
-       \p{Nd}. Note that this also applies to \b, because  it  is  defined  in
-       terms of \w and \W.
+       test characters of any code value, but, by default, the characters that
+       PCRE  recognizes  as digits, spaces, or word characters remain the same
+       set as before, all with values less than 256. This  remains  true  even
+       when  PCRE  is built to include Unicode property support, because to do
+       otherwise would slow down PCRE in many common  cases.  Note  that  this
+       also applies to \b, because it is defined in terms of \w and \W. If you
+       really want to test for a wider sense of, say,  "digit",  you  can  use
+       explicit  Unicode property tests such as \p{Nd}.  Alternatively, if you
+       set the PCRE_UCP option, the way that the  character  escapes  work  is
+       changed  so that Unicode properties are used to determine which charac-
+       ters match. There are more details in the section on generic  character
+       types in the pcrepattern documentation.
 
        7.  Similarly,  characters that match the POSIX named character classes
-       are all low-valued characters.
+       are all low-valued characters, unless the PCRE_UCP option is set.
 
        8. However, the Perl 5.10 horizontal and vertical  whitespace  matching
        escapes (\h, \H, \v, and \V) do match all the appropriate Unicode char-
-       acters.
+       acters, whether or not PCRE_UCP is set.
 
        9. Case-insensitive matching applies only to  characters  whose  values
        are  less than 128, unless PCRE is built with Unicode property support.
@@ -263,7 +267,7 @@ AUTHOR
 
 REVISION
 
-       Last updated: 01 March 2010
+       Last updated: 12 May 2010
        Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
@@ -902,6 +906,12 @@ PCRE API OVERVIEW
        bers for the library.  Applications can use these  to  include  support
        for different releases of PCRE.
 
+       In a Windows environment, if you want to statically link an application
+       program against a non-dll pcre.a  file,  you  must  define  PCRE_STATIC
+       before  including  pcre.h or pcrecpp.h, because otherwise the pcre_mal-
+       loc()   and   pcre_free()   exported   functions   will   be   declared
+       __declspec(dllimport), with unwanted results.
+
        The   functions   pcre_compile(),  pcre_compile2(),  pcre_study(),  and
        pcre_exec() are used for compiling and matching regular expressions  in
        a  Perl-compatible  manner. A sample program that demonstrates the sim-
@@ -1281,48 +1291,49 @@ COMPILING A PATTERN
        letter that has no special meaning  causes  an  error,  thus  reserving
        these  combinations  for  future  expansion.  By default, as in Perl, a
        backslash followed by a letter with no special meaning is treated as  a
-       literal.  (Perl can, however, be persuaded to give a warning for this.)
-       There are at present no other features controlled by  this  option.  It
-       can also be set by a (?X) option setting within a pattern.
+       literal. (Perl can, however, be persuaded to give an error for this, by
+       running it with the -w option.) There are at present no other  features
+       controlled  by this option. It can also be set by a (?X) option setting
+       within a pattern.
 
          PCRE_FIRSTLINE
 
-       If  this  option  is  set,  an  unanchored pattern is required to match
-       before or at the first  newline  in  the  subject  string,  though  the
+       If this option is set, an  unanchored  pattern  is  required  to  match
+       before  or  at  the  first  newline  in  the subject string, though the
        matched text may continue over the newline.
 
          PCRE_JAVASCRIPT_COMPAT
 
        If this option is set, PCRE's behaviour is changed in some ways so that
-       it is compatible with JavaScript rather than Perl. The changes  are  as
+       it  is  compatible with JavaScript rather than Perl. The changes are as
        follows:
 
-       (1)  A  lone  closing square bracket in a pattern causes a compile-time
-       error, because this is illegal in JavaScript (by default it is  treated
+       (1) A lone closing square bracket in a pattern  causes  a  compile-time
+       error,  because this is illegal in JavaScript (by default it is treated
        as a data character). Thus, the pattern AB]CD becomes illegal when this
        option is set.
 
-       (2) At run time, a back reference to an unset subpattern group  matches
-       an  empty  string (by default this causes the current matching alterna-
-       tive to fail). A pattern such as (\1)(a) succeeds when this  option  is
-       set  (assuming  it can find an "a" in the subject), whereas it fails by
+       (2)  At run time, a back reference to an unset subpattern group matches
+       an empty string (by default this causes the current  matching  alterna-
+       tive  to  fail). A pattern such as (\1)(a) succeeds when this option is
+       set (assuming it can find an "a" in the subject), whereas it  fails  by
        default, for Perl compatibility.
 
          PCRE_MULTILINE
 
-       By default, PCRE treats the subject string as consisting  of  a  single
-       line  of characters (even if it actually contains newlines). The "start
-       of line" metacharacter (^) matches only at the  start  of  the  string,
-       while  the  "end  of line" metacharacter ($) matches only at the end of
+       By  default,  PCRE  treats the subject string as consisting of a single
+       line of characters (even if it actually contains newlines). The  "start
+       of  line"  metacharacter  (^)  matches only at the start of the string,
+       while the "end of line" metacharacter ($) matches only at  the  end  of
        the string, or before a terminating newline (unless PCRE_DOLLAR_ENDONLY
        is set). This is the same as Perl.
 
-       When  PCRE_MULTILINE  it  is set, the "start of line" and "end of line"
-       constructs match immediately following or immediately  before  internal
-       newlines  in  the  subject string, respectively, as well as at the very
-       start and end. This is equivalent to Perl's /m option, and  it  can  be
+       When PCRE_MULTILINE it is set, the "start of line" and  "end  of  line"
+       constructs  match  immediately following or immediately before internal
+       newlines in the subject string, respectively, as well as  at  the  very
+       start  and  end.  This is equivalent to Perl's /m option, and it can be
        changed within a pattern by a (?m) option setting. If there are no new-
-       lines in a subject string, or no occurrences of ^ or $  in  a  pattern,
+       lines  in  a  subject string, or no occurrences of ^ or $ in a pattern,
        setting PCRE_MULTILINE has no effect.
 
          PCRE_NEWLINE_CR
@@ -1331,32 +1342,32 @@ COMPILING A PATTERN
          PCRE_NEWLINE_ANYCRLF
          PCRE_NEWLINE_ANY
 
-       These  options  override the default newline definition that was chosen
-       when PCRE was built. Setting the first or the second specifies  that  a
-       newline  is  indicated  by a single character (CR or LF, respectively).
-       Setting PCRE_NEWLINE_CRLF specifies that a newline is indicated by  the
-       two-character  CRLF  sequence.  Setting  PCRE_NEWLINE_ANYCRLF specifies
+       These options override the default newline definition that  was  chosen
+       when  PCRE  was built. Setting the first or the second specifies that a
+       newline is indicated by a single character (CR  or  LF,  respectively).
+       Setting  PCRE_NEWLINE_CRLF specifies that a newline is indicated by the
+       two-character CRLF  sequence.  Setting  PCRE_NEWLINE_ANYCRLF  specifies
        that any of the three preceding sequences should be recognized. Setting
-       PCRE_NEWLINE_ANY  specifies that any Unicode newline sequence should be
+       PCRE_NEWLINE_ANY specifies that any Unicode newline sequence should  be
        recognized. The Unicode newline sequences are the three just mentioned,
-       plus  the  single  characters  VT (vertical tab, U+000B), FF (formfeed,
-       U+000C), NEL (next line, U+0085), LS (line separator, U+2028),  and  PS
-       (paragraph  separator,  U+2029).  The  last  two are recognized only in
+       plus the single characters VT (vertical  tab,  U+000B),  FF  (formfeed,
+       U+000C),  NEL  (next line, U+0085), LS (line separator, U+2028), and PS
+       (paragraph separator, U+2029). The last  two  are  recognized  only  in
        UTF-8 mode.
 
-       The newline setting in the  options  word  uses  three  bits  that  are
+       The  newline  setting  in  the  options  word  uses three bits that are
        treated as a number, giving eight possibilities. Currently only six are
-       used (default plus the five values above). This means that if  you  set
-       more  than one newline option, the combination may or may not be sensi-
+       used  (default  plus the five values above). This means that if you set
+       more than one newline option, the combination may or may not be  sensi-
        ble. For example, PCRE_NEWLINE_CR with PCRE_NEWLINE_LF is equivalent to
-       PCRE_NEWLINE_CRLF,  but other combinations may yield unused numbers and
+       PCRE_NEWLINE_CRLF, but other combinations may yield unused numbers  and
        cause an error.
 
-       The only time that a line break is specially recognized when  compiling
-       a  pattern  is  if  PCRE_EXTENDED  is set, and an unescaped # outside a
-       character class is encountered. This indicates  a  comment  that  lasts
-       until  after the next line break sequence. In other circumstances, line
-       break  sequences  are  treated  as  literal  data,   except   that   in
+       The  only time that a line break is specially recognized when compiling
+       a pattern is if PCRE_EXTENDED is set, and  an  unescaped  #  outside  a
+       character  class  is  encountered.  This indicates a comment that lasts
+       until after the next line break sequence. In other circumstances,  line
+       break   sequences   are   treated  as  literal  data,  except  that  in
        PCRE_EXTENDED mode, both CR and LF are treated as whitespace characters
        and are therefore ignored.
 
@@ -1366,46 +1377,56 @@ COMPILING A PATTERN
          PCRE_NO_AUTO_CAPTURE
 
        If this option is set, it disables the use of numbered capturing paren-
-       theses in the pattern. Any opening parenthesis that is not followed  by
-       ?  behaves as if it were followed by ?: but named parentheses can still
-       be used for capturing (and they acquire  numbers  in  the  usual  way).
+       theses  in the pattern. Any opening parenthesis that is not followed by
+       ? behaves as if it were followed by ?: but named parentheses can  still
+       be  used  for  capturing  (and  they acquire numbers in the usual way).
        There is no equivalent of this option in Perl.
 
+         PCRE_UCP
+
+       This option changes the way PCRE processes \b, \d, \s, \w, and some  of
+       the POSIX character classes. By default, only ASCII characters are rec-
+       ognized, but if PCRE_UCP is set, Unicode properties are used instead to
+       classify  characters.  More details are given in the section on generic
+       character types in the pcrepattern page. If you set PCRE_UCP,  matching
+       one  of the items it affects takes much longer. The option is available
+       only if PCRE has been compiled with Unicode property support.
+
          PCRE_UNGREEDY
 
-       This  option  inverts  the "greediness" of the quantifiers so that they
-       are not greedy by default, but become greedy if followed by "?". It  is
-       not  compatible  with Perl. It can also be set by a (?U) option setting
+       This option inverts the "greediness" of the quantifiers  so  that  they
+       are  not greedy by default, but become greedy if followed by "?". It is
+       not compatible with Perl. It can also be set by a (?U)  option  setting
        within the pattern.
 
          PCRE_UTF8
 
-       This option causes PCRE to regard both the pattern and the  subject  as
-       strings  of  UTF-8 characters instead of single-byte character strings.
-       However, it is available only when PCRE is built to include UTF-8  sup-
-       port.  If not, the use of this option provokes an error. Details of how
-       this option changes the behaviour of PCRE are given in the  section  on
+       This  option  causes PCRE to regard both the pattern and the subject as
+       strings of UTF-8 characters instead of single-byte  character  strings.
+       However,  it is available only when PCRE is built to include UTF-8 sup-
+       port. If not, the use of this option provokes an error. Details of  how
+       this  option  changes the behaviour of PCRE are given in the section on
        UTF-8 support in the main pcre page.
 
          PCRE_NO_UTF8_CHECK
 
        When PCRE_UTF8 is set, the validity of the pattern as a UTF-8 string is
-       automatically checked. There is a  discussion  about  the  validity  of
-       UTF-8  strings  in  the main pcre page. If an invalid UTF-8 sequence of
-       bytes is found, pcre_compile() returns an error. If  you  already  know
+       automatically  checked.  There  is  a  discussion about the validity of
+       UTF-8 strings in the main pcre page. If an invalid  UTF-8  sequence  of
+       bytes  is  found,  pcre_compile() returns an error. If you already know
        that your pattern is valid, and you want to skip this check for perfor-
-       mance reasons, you can set the PCRE_NO_UTF8_CHECK option.  When  it  is
-       set,  the  effect  of  passing  an invalid UTF-8 string as a pattern is
-       undefined. It may cause your program to crash. Note  that  this  option
-       can  also be passed to pcre_exec() and pcre_dfa_exec(), to suppress the
+       mance  reasons,  you  can set the PCRE_NO_UTF8_CHECK option. When it is
+       set, the effect of passing an invalid UTF-8  string  as  a  pattern  is
+       undefined.  It  may  cause your program to crash. Note that this option
+       can also be passed to pcre_exec() and pcre_dfa_exec(), to suppress  the
        UTF-8 validity checking of subject strings.
 
 
 COMPILATION ERROR CODES
 
-       The following table lists the error  codes  than  may  be  returned  by
-       pcre_compile2(),  along with the error messages that may be returned by
-       both compiling functions. As PCRE has developed, some error codes  have
+       The  following  table  lists  the  error  codes than may be returned by
+       pcre_compile2(), along with the error messages that may be returned  by
+       both  compiling functions. As PCRE has developed, some error codes have
        fallen out of use. To avoid confusion, they have not been re-used.
 
           0  no error
@@ -1461,20 +1482,24 @@ COMPILATION ERROR CODES
          50  [this code is not in use]
          51  octal value is greater than \377 (not in UTF-8 mode)
          52  internal error: overran compiling workspace
-         53   internal  error:  previously-checked  referenced  subpattern not
-       found
+         53  internal error: previously-checked referenced subpattern
+               not found
          54  DEFINE group contains more than one branch
          55  repeating a DEFINE group is not allowed
          56  inconsistent NEWLINE options
          57  \g is not followed by a braced, angle-bracketed, or quoted
                name/number or by a plain number
          58  a numbered reference must not be zero
-         59  (*VERB) with an argument is not supported
+         59  an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)
          60  (*VERB) not recognized
          61  number is too big
          62  subpattern name expected
          63  digit expected after (?+
          64  ] is an invalid data character in JavaScript compatibility mode
+         65  different names for subpatterns of the same number are
+               not allowed
+         66  (*MARK) must have an argument
+         67  this version of PCRE is not compiled with PCRE_UCP support
 
        The numbers 32 and 10000 in errors 48 and 49  are  defaults;  different
        values may be used if the limits were changed when PCRE was built.
@@ -1534,59 +1559,68 @@ STUDYING A PATTERN
        bytes  is  created. This speeds up finding a position in the subject at
        which to start matching.
 
+       The two optimizations just described can be  disabled  by  setting  the
+       PCRE_NO_START_OPTIMIZE    option    when    calling    pcre_exec()   or
+       pcre_dfa_exec(). You might want to do this  if  your  pattern  contains
+       callouts,  or  make  use of (*MARK), and you make use of these in cases
+       where matching fails.  See  the  discussion  of  PCRE_NO_START_OPTIMIZE
+       below.
+
 
 LOCALE SUPPORT
 
-       PCRE handles caseless matching, and determines whether  characters  are
-       letters,  digits, or whatever, by reference to a set of tables, indexed
-       by character value. When running in UTF-8 mode, this  applies  only  to
-       characters  with  codes  less than 128. Higher-valued codes never match
-       escapes such as \w or \d, but can be tested with \p if  PCRE  is  built
-       with  Unicode  character property support. The use of locales with Uni-
-       code is discouraged. If you are handling characters with codes  greater
-       than  128, you should either use UTF-8 and Unicode, or use locales, but
-       not try to mix the two.
-
-       PCRE contains an internal set of tables that are used  when  the  final
-       argument  of  pcre_compile()  is  NULL.  These  are sufficient for many
+       PCRE  handles  caseless matching, and determines whether characters are
+       letters, digits, or whatever, by reference to a set of tables,  indexed
+       by  character  value.  When running in UTF-8 mode, this applies only to
+       characters with codes less than 128. By  default,  higher-valued  codes
+       never match escapes such as \w or \d, but they can be tested with \p if
+       PCRE is built with Unicode character property  support.  Alternatively,
+       the  PCRE_UCP  option  can  be  set at compile time; this causes \w and
+       friends to use Unicode property support instead of built-in tables. The
+       use of locales with Unicode is discouraged. If you are handling charac-
+       ters with codes greater than 128, you should either use UTF-8 and  Uni-
+       code, or use locales, but not try to mix the two.
+
+       PCRE  contains  an  internal set of tables that are used when the final
+       argument of pcre_compile() is  NULL.  These  are  sufficient  for  many
        applications.  Normally, the internal tables recognize only ASCII char-
        acters. However, when PCRE is built, it is possible to cause the inter-
        nal tables to be rebuilt in the default "C" locale of the local system,
        which may cause them to be different.
 
-       The  internal tables can always be overridden by tables supplied by the
+       The internal tables can always be overridden by tables supplied by  the
        application that calls PCRE. These may be created in a different locale
-       from  the  default.  As more and more applications change to using Uni-
+       from the default. As more and more applications change  to  using  Uni-
        code, the need for this locale support is expected to die away.
 
-       External tables are built by calling  the  pcre_maketables()  function,
-       which  has no arguments, in the relevant locale. The result can then be
-       passed to pcre_compile() or pcre_exec()  as  often  as  necessary.  For
-       example,  to  build  and use tables that are appropriate for the French
-       locale (where accented characters with  values  greater  than  128  are
+       External  tables  are  built by calling the pcre_maketables() function,
+       which has no arguments, in the relevant locale. The result can then  be
+       passed  to  pcre_compile()  or  pcre_exec()  as often as necessary. For
+       example, to build and use tables that are appropriate  for  the  French
+       locale  (where  accented  characters  with  values greater than 128 are
        treated as letters), the following code could be used:
 
          setlocale(LC_CTYPE, "fr_FR");
          tables = pcre_maketables();
          re = pcre_compile(..., tables);
 
-       The  locale  name "fr_FR" is used on Linux and other Unix-like systems;
+       The locale name "fr_FR" is used on Linux and other  Unix-like  systems;
        if you are using Windows, the name for the French locale is "french".
 
-       When pcre_maketables() runs, the tables are built  in  memory  that  is
-       obtained  via  pcre_malloc. It is the caller's responsibility to ensure
-       that the memory containing the tables remains available for as long  as
+       When  pcre_maketables()  runs,  the  tables are built in memory that is
+       obtained via pcre_malloc. It is the caller's responsibility  to  ensure
+       that  the memory containing the tables remains available for as long as
        it is needed.
 
        The pointer that is passed to pcre_compile() is saved with the compiled
-       pattern, and the same tables are used via this pointer by  pcre_study()
+       pattern,  and the same tables are used via this pointer by pcre_study()
        and normally also by pcre_exec(). Thus, by default, for any single pat-
        tern, compilation, studying and matching all happen in the same locale,
        but different patterns can be compiled in different locales.
 
-       It  is  possible to pass a table pointer or NULL (indicating the use of
-       the internal tables) to pcre_exec(). Although  not  intended  for  this
-       purpose,  this facility could be used to match a pattern in a different
+       It is possible to pass a table pointer or NULL (indicating the  use  of
+       the  internal  tables)  to  pcre_exec(). Although not intended for this
+       purpose, this facility could be used to match a pattern in a  different
        locale from the one in which it was compiled. Passing table pointers at
        run time is discussed below in the section on matching a pattern.
 
@@ -1596,15 +1630,15 @@ INFORMATION ABOUT A PATTERN
        int pcre_fullinfo(const pcre *code, const pcre_extra *extra,
             int what, void *where);
 
-       The  pcre_fullinfo() function returns information about a compiled pat-
+       The pcre_fullinfo() function returns information about a compiled  pat-
        tern. It replaces the obsolete pcre_info() function, which is neverthe-
        less retained for backwards compability (and is documented below).
 
-       The  first  argument  for  pcre_fullinfo() is a pointer to the compiled
-       pattern. The second argument is the result of pcre_study(), or NULL  if
-       the  pattern  was not studied. The third argument specifies which piece
-       of information is required, and the fourth argument is a pointer  to  a
-       variable  to  receive  the  data. The yield of the function is zero for
+       The first argument for pcre_fullinfo() is a  pointer  to  the  compiled
+       pattern.  The second argument is the result of pcre_study(), or NULL if
+       the pattern was not studied. The third argument specifies  which  piece
+       of  information  is required, and the fourth argument is a pointer to a
+       variable to receive the data. The yield of the  function  is  zero  for
        success, or one of the following negative numbers:
 
          PCRE_ERROR_NULL       the argument code was NULL
@@ -1612,9 +1646,9 @@ INFORMATION ABOUT A PATTERN
          PCRE_ERROR_BADMAGIC   the "magic number" was not found
          PCRE_ERROR_BADOPTION  the value of what was invalid
 
-       The "magic number" is placed at the start of each compiled  pattern  as
-       an  simple check against passing an arbitrary memory pointer. Here is a
-       typical call of pcre_fullinfo(), to obtain the length of  the  compiled
+       The  "magic  number" is placed at the start of each compiled pattern as
+       an simple check against passing an arbitrary memory pointer. Here is  a
+       typical  call  of pcre_fullinfo(), to obtain the length of the compiled
        pattern:
 
          int rc;
@@ -1625,131 +1659,131 @@ INFORMATION ABOUT A PATTERN
            PCRE_INFO_SIZE,   /* what is required */
            &length);         /* where to put the data */
 
-       The  possible  values for the third argument are defined in pcre.h, and
+       The possible values for the third argument are defined in  pcre.h,  and
        are as follows:
 
          PCRE_INFO_BACKREFMAX
 
-       Return the number of the highest back reference  in  the  pattern.  The
-       fourth  argument  should  point to an int variable. Zero is returned if
+       Return  the  number  of  the highest back reference in the pattern. The
+       fourth argument should point to an int variable. Zero  is  returned  if
        there are no back references.
 
          PCRE_INFO_CAPTURECOUNT
 
-       Return the number of capturing subpatterns in the pattern.  The  fourth
+       Return  the  number of capturing subpatterns in the pattern. The fourth
        argument should point to an int variable.
 
          PCRE_INFO_DEFAULT_TABLES
 
-       Return  a pointer to the internal default character tables within PCRE.
-       The fourth argument should point to an unsigned char *  variable.  This
+       Return a pointer to the internal default character tables within  PCRE.
+       The  fourth  argument should point to an unsigned char * variable. This
        information call is provided for internal use by the pcre_study() func-
-       tion. External callers can cause PCRE to use  its  internal  tables  by
+       tion.  External  callers  can  cause PCRE to use its internal tables by
        passing a NULL table pointer.
 
          PCRE_INFO_FIRSTBYTE
 
-       Return  information  about  the first byte of any matched string, for a
-       non-anchored pattern. The fourth argument should point to an int  vari-
-       able.  (This option used to be called PCRE_INFO_FIRSTCHAR; the old name
+       Return information about the first byte of any matched  string,  for  a
+       non-anchored  pattern. The fourth argument should point to an int vari-
+       able. (This option used to be called PCRE_INFO_FIRSTCHAR; the old  name
        is still recognized for backwards compatibility.)
 
-       If there is a fixed first byte, for example, from  a  pattern  such  as
+       If  there  is  a  fixed first byte, for example, from a pattern such as
        (cat|cow|coyote), its value is returned. Otherwise, if either
 
-       (a)  the pattern was compiled with the PCRE_MULTILINE option, and every
+       (a) the pattern was compiled with the PCRE_MULTILINE option, and  every
        branch starts with "^", or
 
        (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not
        set (if it were set, the pattern would be anchored),
 
-       -1  is  returned, indicating that the pattern matches only at the start
-       of a subject string or after any newline within the  string.  Otherwise
+       -1 is returned, indicating that the pattern matches only at  the  start
+       of  a  subject string or after any newline within the string. Otherwise
        -2 is returned. For anchored patterns, -2 is returned.
 
          PCRE_INFO_FIRSTTABLE
 
-       If  the pattern was studied, and this resulted in the construction of a
+       If the pattern was studied, and this resulted in the construction of  a
        256-bit table indicating a fixed set of bytes for the first byte in any
-       matching  string, a pointer to the table is returned. Otherwise NULL is
-       returned. The fourth argument should point to an unsigned char *  vari-
+       matching string, a pointer to the table is returned. Otherwise NULL  is
+       returned.  The fourth argument should point to an unsigned char * vari-
        able.
 
          PCRE_INFO_HASCRORLF
 
-       Return  1  if  the  pattern  contains any explicit matches for CR or LF
-       characters, otherwise 0. The fourth argument should  point  to  an  int
-       variable.  An explicit match is either a literal CR or LF character, or
+       Return 1 if the pattern contains any explicit  matches  for  CR  or  LF
+       characters,  otherwise  0.  The  fourth argument should point to an int
+       variable. An explicit match is either a literal CR or LF character,  or
        \r or \n.
 
          PCRE_INFO_JCHANGED
 
-       Return 1 if the (?J) or (?-J) option setting is used  in  the  pattern,
-       otherwise  0. The fourth argument should point to an int variable. (?J)
+       Return  1  if  the (?J) or (?-J) option setting is used in the pattern,
+       otherwise 0. The fourth argument should point to an int variable.  (?J)
        and (?-J) set and unset the local PCRE_DUPNAMES option, respectively.
 
          PCRE_INFO_LASTLITERAL
 
-       Return the value of the rightmost literal byte that must exist  in  any
-       matched  string,  other  than  at  its  start,  if such a byte has been
+       Return  the  value of the rightmost literal byte that must exist in any
+       matched string, other than at its  start,  if  such  a  byte  has  been
        recorded. The fourth argument should point to an int variable. If there
-       is  no such byte, -1 is returned. For anchored patterns, a last literal
-       byte is recorded only if it follows something of variable  length.  For
+       is no such byte, -1 is returned. For anchored patterns, a last  literal
+       byte  is  recorded only if it follows something of variable length. For
        example, for the pattern /^a\d+z\d+/ the returned value is "z", but for
        /^a\dz\d/ the returned value is -1.
 
          PCRE_INFO_MINLENGTH
 
-       If the pattern was studied and a minimum length  for  matching  subject
-       strings  was  computed,  its  value is returned. Otherwise the returned
-       value is -1. The value is a number of characters, not bytes  (this  may
-       be  relevant in UTF-8 mode). The fourth argument should point to an int
-       variable. A non-negative value is a lower bound to the  length  of  any
-       matching  string.  There  may not be any strings of that length that do
+       If  the  pattern  was studied and a minimum length for matching subject
+       strings was computed, its value is  returned.  Otherwise  the  returned
+       value  is  -1. The value is a number of characters, not bytes (this may
+       be relevant in UTF-8 mode). The fourth argument should point to an  int
+       variable.  A  non-negative  value is a lower bound to the length of any
+       matching string. There may not be any strings of that  length  that  do
        actually match, but every string that does match is at least that long.
 
          PCRE_INFO_NAMECOUNT
          PCRE_INFO_NAMEENTRYSIZE
          PCRE_INFO_NAMETABLE
 
-       PCRE supports the use of named as well as numbered capturing  parenthe-
-       ses.  The names are just an additional way of identifying the parenthe-
+       PCRE  supports the use of named as well as numbered capturing parenthe-
+       ses. The names are just an additional way of identifying the  parenthe-
        ses, which still acquire numbers. Several convenience functions such as
-       pcre_get_named_substring()  are  provided  for extracting captured sub-
-       strings by name. It is also possible to extract the data  directly,  by
-       first  converting  the  name to a number in order to access the correct
+       pcre_get_named_substring() are provided for  extracting  captured  sub-
+       strings  by  name. It is also possible to extract the data directly, by
+       first converting the name to a number in order to  access  the  correct
        pointers in the output vector (described with pcre_exec() below). To do
-       the  conversion,  you  need  to  use  the  name-to-number map, which is
+       the conversion, you need  to  use  the  name-to-number  map,  which  is
        described by these three values.
 
        The map consists of a number of fixed-size entries. PCRE_INFO_NAMECOUNT
        gives the number of entries, and PCRE_INFO_NAMEENTRYSIZE gives the size
-       of each entry; both of these  return  an  int  value.  The  entry  size
-       depends  on the length of the longest name. PCRE_INFO_NAMETABLE returns
-       a pointer to the first entry of the table  (a  pointer  to  char).  The
+       of  each  entry;  both  of  these  return  an int value. The entry size
+       depends on the length of the longest name. PCRE_INFO_NAMETABLE  returns
+       a  pointer  to  the  first  entry of the table (a pointer to char). The
        first two bytes of each entry are the number of the capturing parenthe-
-       sis, most significant byte first. The rest of the entry is  the  corre-
+       sis,  most  significant byte first. The rest of the entry is the corre-
        sponding name, zero terminated.
 
-       The  names are in alphabetical order. Duplicate names may appear if (?|
+       The names are in alphabetical order. Duplicate names may appear if  (?|
        is used to create multiple groups with the same number, as described in
-       the  section  on  duplicate subpattern numbers in the pcrepattern page.
-       Duplicate names for subpatterns with different  numbers  are  permitted
-       only  if  PCRE_DUPNAMES  is  set. In all cases of duplicate names, they
-       appear in the table in the order in which they were found in  the  pat-
-       tern.  In  the  absence  of (?| this is the order of increasing number;
+       the section on duplicate subpattern numbers in  the  pcrepattern  page.
+       Duplicate  names  for  subpatterns with different numbers are permitted
+       only if PCRE_DUPNAMES is set. In all cases  of  duplicate  names,  they
+       appear  in  the table in the order in which they were found in the pat-
+       tern. In the absence of (?| this is the  order  of  increasing  number;
        when (?| is used this is not necessarily the case because later subpat-
        terns may have lower numbers.
 
-       As  a  simple  example of the name/number table, consider the following
-       pattern (assume PCRE_EXTENDED is set, so white space -  including  new-
+       As a simple example of the name/number table,  consider  the  following
+       pattern  (assume  PCRE_EXTENDED is set, so white space - including new-
        lines - is ignored):
 
          (?<date> (?<year>(\d\d)?\d\d) -
          (?<month>\d\d) - (?<day>\d\d) )
 
-       There  are  four  named subpatterns, so the table has four entries, and
-       each entry in the table is eight bytes long. The table is  as  follows,
+       There are four named subpatterns, so the table has  four  entries,  and
+       each  entry  in the table is eight bytes long. The table is as follows,
        with non-printing bytes shows in hexadecimal, and undefined bytes shown
        as ??:
 
@@ -1758,31 +1792,31 @@ INFORMATION ABOUT A PATTERN
          00 04 m  o  n  t  h  00
          00 02 y  e  a  r  00 ??
 
-       When writing code to extract data  from  named  subpatterns  using  the
-       name-to-number  map,  remember that the length of the entries is likely
+       When  writing  code  to  extract  data from named subpatterns using the
+       name-to-number map, remember that the length of the entries  is  likely
        to be different for each compiled pattern.
 
          PCRE_INFO_OKPARTIAL
 
-       Return 1  if  the  pattern  can  be  used  for  partial  matching  with
-       pcre_exec(),  otherwise  0.  The fourth argument should point to an int
-       variable. From  release  8.00,  this  always  returns  1,  because  the
-       restrictions  that  previously  applied  to  partial matching have been
-       lifted. The pcrepartial documentation gives details of  partial  match-
+       Return  1  if  the  pattern  can  be  used  for  partial  matching with
+       pcre_exec(), otherwise 0. The fourth argument should point  to  an  int
+       variable.  From  release  8.00,  this  always  returns  1,  because the
+       restrictions that previously applied  to  partial  matching  have  been
+       lifted.  The  pcrepartial documentation gives details of partial match-
        ing.
 
          PCRE_INFO_OPTIONS
 
-       Return  a  copy of the options with which the pattern was compiled. The
-       fourth argument should point to an unsigned long  int  variable.  These
+       Return a copy of the options with which the pattern was  compiled.  The
+       fourth  argument  should  point to an unsigned long int variable. These
        option bits are those specified in the call to pcre_compile(), modified
        by any top-level option settings at the start of the pattern itself. In
-       other  words,  they are the options that will be in force when matching
-       starts. For example, if the pattern /(?im)abc(?-i)d/ is  compiled  with
-       the  PCRE_EXTENDED option, the result is PCRE_CASELESS, PCRE_MULTILINE,
+       other words, they are the options that will be in force  when  matching
+       starts.  For  example, if the pattern /(?im)abc(?-i)d/ is compiled with
+       the PCRE_EXTENDED option, the result is PCRE_CASELESS,  PCRE_MULTILINE,
        and PCRE_EXTENDED.
 
-       A pattern is automatically anchored by PCRE if  all  of  its  top-level
+       A  pattern  is  automatically  anchored by PCRE if all of its top-level
        alternatives begin with one of the following:
 
          ^     unless PCRE_MULTILINE is set
@@ -1796,7 +1830,7 @@ INFORMATION ABOUT A PATTERN
 
          PCRE_INFO_SIZE
 
-       Return the size of the compiled pattern, that is, the  value  that  was
+       Return  the  size  of the compiled pattern, that is, the value that was
        passed as the argument to pcre_malloc() when PCRE was getting memory in
        which to place the compiled data. The fourth argument should point to a
        size_t variable.
@@ -1804,10 +1838,10 @@ INFORMATION ABOUT A PATTERN
          PCRE_INFO_STUDYSIZE
 
        Return the size of the data block pointed to by the study_data field in
-       a pcre_extra block. That is,  it  is  the  value  that  was  passed  to
+       a  pcre_extra  block.  That  is,  it  is  the  value that was passed to
        pcre_malloc() when PCRE was getting memory into which to place the data
-       created by pcre_study(). If pcre_extra is NULL, or there  is  no  study
-       data,  zero  is  returned. The fourth argument should point to a size_t
+       created  by  pcre_study().  If pcre_extra is NULL, or there is no study
+       data, zero is returned. The fourth argument should point  to  a  size_t
        variable.
 
 
@@ -1815,21 +1849,21 @@ OBSOLETE INFO FUNCTION
 
        int pcre_info(const pcre *code, int *optptr, int *firstcharptr);
 
-       The pcre_info() function is now obsolete because its interface  is  too
-       restrictive  to return all the available data about a compiled pattern.
-       New  programs  should  use  pcre_fullinfo()  instead.  The   yield   of
-       pcre_info()  is the number of capturing subpatterns, or one of the fol-
+       The  pcre_info()  function is now obsolete because its interface is too
+       restrictive to return all the available data about a compiled  pattern.
+       New   programs   should  use  pcre_fullinfo()  instead.  The  yield  of
+       pcre_info() is the number of capturing subpatterns, or one of the  fol-
        lowing negative numbers:
 
          PCRE_ERROR_NULL       the argument code was NULL
          PCRE_ERROR_BADMAGIC   the "magic number" was not found
 
-       If the optptr argument is not NULL, a copy of the  options  with  which
-       the  pattern  was  compiled  is placed in the integer it points to (see
+       If  the  optptr  argument is not NULL, a copy of the options with which
+       the pattern was compiled is placed in the integer  it  points  to  (see
        PCRE_INFO_OPTIONS above).
 
-       If the pattern is not anchored and the  firstcharptr  argument  is  not
-       NULL,  it is used to pass back information about the first character of
+       If  the  pattern  is  not anchored and the firstcharptr argument is not
+       NULL, it is used to pass back information about the first character  of
        any matched string (see PCRE_INFO_FIRSTBYTE above).
 
 
@@ -1837,21 +1871,21 @@ REFERENCE COUNTS
 
        int pcre_refcount(pcre *code, int adjust);
 
-       The pcre_refcount() function is used to maintain a reference  count  in
+       The  pcre_refcount()  function is used to maintain a reference count in
        the data block that contains a compiled pattern. It is provided for the
-       benefit of applications that  operate  in  an  object-oriented  manner,
+       benefit  of  applications  that  operate  in an object-oriented manner,
        where different parts of the application may be using the same compiled
        pattern, but you want to free the block when they are all done.
 
        When a pattern is compiled, the reference count field is initialized to
-       zero.   It is changed only by calling this function, whose action is to
-       add the adjust value (which may be positive or  negative)  to  it.  The
+       zero.  It is changed only by calling this function, whose action is  to
+       add  the  adjust  value  (which may be positive or negative) to it. The
        yield of the function is the new value. However, the value of the count
-       is constrained to lie between 0 and 65535, inclusive. If the new  value
+       is  constrained to lie between 0 and 65535, inclusive. If the new value
        is outside these limits, it is forced to the appropriate limit value.
 
-       Except  when it is zero, the reference count is not correctly preserved
-       if a pattern is compiled on one host and then  transferred  to  a  host
+       Except when it is zero, the reference count is not correctly  preserved
+       if  a  pattern  is  compiled on one host and then transferred to a host
        whose byte-order is different. (This seems a highly unlikely scenario.)
 
 
@@ -1861,18 +1895,18 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
             const char *subject, int length, int startoffset,
             int options, int *ovector, int ovecsize);
 
-       The  function pcre_exec() is called to match a subject string against a
-       compiled pattern, which is passed in the code argument. If the  pattern
-       was  studied,  the  result  of  the study should be passed in the extra
-       argument. This function is the main matching facility of  the  library,
+       The function pcre_exec() is called to match a subject string against  a
+       compiled  pattern, which is passed in the code argument. If the pattern
+       was studied, the result of the study should  be  passed  in  the  extra
+       argument.  This  function is the main matching facility of the library,
        and it operates in a Perl-like manner. For specialist use there is also
-       an alternative matching function, which is described below in the  sec-
+       an  alternative matching function, which is described below in the sec-
        tion about the pcre_dfa_exec() function.
 
-       In  most applications, the pattern will have been compiled (and option-
-       ally studied) in the same process that calls pcre_exec().  However,  it
+       In most applications, the pattern will have been compiled (and  option-
+       ally  studied)  in the same process that calls pcre_exec(). However, it
        is possible to save compiled patterns and study data, and then use them
-       later in different processes, possibly even on different hosts.  For  a
+       later  in  different processes, possibly even on different hosts. For a
        discussion about this, see the pcreprecompile documentation.
 
        Here is an example of a simple call to pcre_exec():
@@ -1891,10 +1925,10 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
 
    Extra data for pcre_exec()
 
-       If  the  extra argument is not NULL, it must point to a pcre_extra data
-       block. The pcre_study() function returns such a block (when it  doesn't
-       return  NULL), but you can also create one for yourself, and pass addi-
-       tional information in it. The pcre_extra block contains  the  following
+       If the extra argument is not NULL, it must point to a  pcre_extra  data
+       block.  The pcre_study() function returns such a block (when it doesn't
+       return NULL), but you can also create one for yourself, and pass  addi-
+       tional  information  in it. The pcre_extra block contains the following
        fields (not necessarily in this order):
 
          unsigned long int flags;
@@ -1903,8 +1937,9 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          unsigned long int match_limit_recursion;
          void *callout_data;
          const unsigned char *tables;
+         unsigned char **mark;
 
-       The  flags  field  is a bitmap that specifies which of the other fields
+       The flags field is a bitmap that specifies which of  the  other  fields
        are set. The flag bits are:
 
          PCRE_EXTRA_STUDY_DATA
@@ -1912,85 +1947,98 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_EXTRA_MATCH_LIMIT_RECURSION
          PCRE_EXTRA_CALLOUT_DATA
          PCRE_EXTRA_TABLES
+         PCRE_EXTRA_MARK
 
-       Other flag bits should be set to zero. The study_data field is  set  in
-       the  pcre_extra  block  that is returned by pcre_study(), together with
+       Other  flag  bits should be set to zero. The study_data field is set in
+       the pcre_extra block that is returned by  pcre_study(),  together  with
        the appropriate flag bit. You should not set this yourself, but you may
-       add  to  the  block by setting the other fields and their corresponding
+       add to the block by setting the other fields  and  their  corresponding
        flag bits.
 
        The match_limit field provides a means of preventing PCRE from using up
-       a  vast amount of resources when running patterns that are not going to
-       match, but which have a very large number  of  possibilities  in  their
-       search  trees. The classic example is a pattern that uses nested unlim-
+       a vast amount of resources when running patterns that are not going  to
+       match,  but  which  have  a very large number of possibilities in their
+       search trees. The classic example is a pattern that uses nested  unlim-
        ited repeats.
 
-       Internally, PCRE uses a function called match() which it calls  repeat-
-       edly  (sometimes  recursively). The limit set by match_limit is imposed
-       on the number of times this function is called during  a  match,  which
-       has  the  effect  of  limiting the amount of backtracking that can take
+       Internally,  PCRE uses a function called match() which it calls repeat-
+       edly (sometimes recursively). The limit set by match_limit  is  imposed
+       on  the  number  of times this function is called during a match, which
+       has the effect of limiting the amount of  backtracking  that  can  take
        place. For patterns that are not anchored, the count restarts from zero
        for each position in the subject string.
 
-       The  default  value  for  the  limit can be set when PCRE is built; the
-       default default is 10 million, which handles all but the  most  extreme
-       cases.  You  can  override  the  default by suppling pcre_exec() with a
-       pcre_extra    block    in    which    match_limit    is    set,     and
-       PCRE_EXTRA_MATCH_LIMIT  is  set  in  the  flags  field. If the limit is
+       The default value for the limit can be set  when  PCRE  is  built;  the
+       default  default  is 10 million, which handles all but the most extreme
+       cases. You can override the default  by  suppling  pcre_exec()  with  a
+       pcre_extra     block    in    which    match_limit    is    set,    and
+       PCRE_EXTRA_MATCH_LIMIT is set in the  flags  field.  If  the  limit  is
        exceeded, pcre_exec() returns PCRE_ERROR_MATCHLIMIT.
 
-       The match_limit_recursion field is similar to match_limit, but  instead
+       The  match_limit_recursion field is similar to match_limit, but instead
        of limiting the total number of times that match() is called, it limits
-       the depth of recursion. The recursion depth is a  smaller  number  than
-       the  total number of calls, because not all calls to match() are recur-
+       the  depth  of  recursion. The recursion depth is a smaller number than
+       the total number of calls, because not all calls to match() are  recur-
        sive.  This limit is of use only if it is set smaller than match_limit.
 
-       Limiting the recursion depth limits the amount of  stack  that  can  be
+       Limiting  the  recursion  depth  limits the amount of stack that can be
        used, or, when PCRE has been compiled to use memory on the heap instead
        of the stack, the amount of heap memory that can be used.
 
-       The default value for match_limit_recursion can be  set  when  PCRE  is
-       built;  the  default  default  is  the  same  value  as the default for
-       match_limit. You can override the default by suppling pcre_exec()  with
-       a   pcre_extra   block  in  which  match_limit_recursion  is  set,  and
-       PCRE_EXTRA_MATCH_LIMIT_RECURSION is set in  the  flags  field.  If  the
+       The  default  value  for  match_limit_recursion can be set when PCRE is
+       built; the default default  is  the  same  value  as  the  default  for
+       match_limit.  You can override the default by suppling pcre_exec() with
+       a  pcre_extra  block  in  which  match_limit_recursion  is   set,   and
+       PCRE_EXTRA_MATCH_LIMIT_RECURSION  is  set  in  the  flags field. If the
        limit is exceeded, pcre_exec() returns PCRE_ERROR_RECURSIONLIMIT.
 
-       The  callout_data  field is used in conjunction with the "callout" fea-
+       The callout_data field is used in conjunction with the  "callout"  fea-
        ture, and is described in the pcrecallout documentation.
 
-       The tables field  is  used  to  pass  a  character  tables  pointer  to
-       pcre_exec();  this overrides the value that is stored with the compiled
-       pattern. A non-NULL value is stored with the compiled pattern  only  if
-       custom  tables  were  supplied to pcre_compile() via its tableptr argu-
+       The  tables  field  is  used  to  pass  a  character  tables pointer to
+       pcre_exec(); this overrides the value that is stored with the  compiled
+       pattern.  A  non-NULL value is stored with the compiled pattern only if
+       custom tables were supplied to pcre_compile() via  its  tableptr  argu-
        ment.  If NULL is passed to pcre_exec() using this mechanism, it forces
-       PCRE's  internal  tables  to be used. This facility is helpful when re-
-       using patterns that have been saved after compiling  with  an  external
-       set  of  tables,  because  the  external tables might be at a different
-       address when pcre_exec() is called. See the  pcreprecompile  documenta-
+       PCRE's internal tables to be used. This facility is  helpful  when  re-
+       using  patterns  that  have been saved after compiling with an external
+       set of tables, because the external tables  might  be  at  a  different
+       address  when  pcre_exec() is called. See the pcreprecompile documenta-
        tion for a discussion of saving compiled patterns for later use.
 
+       If PCRE_EXTRA_MARK is set in the flags field, the mark  field  must  be
+       set  to  point  to a char * variable. If the pattern contains any back-
+       tracking control verbs such as (*MARK:NAME), and the execution ends  up
+       with  a  name  to  pass back, a pointer to the name string (zero termi-
+       nated) is placed in the variable pointed to  by  the  mark  field.  The
+       names  are  within  the  compiled pattern; if you wish to retain such a
+       name you must copy it before freeing the memory of a compiled  pattern.
+       If  there  is no name to pass back, the variable pointed to by the mark
+       field set to NULL. For details of the backtracking control  verbs,  see
+       the section entitled "Backtracking control" in the pcrepattern documen-
+       tation.
+
    Option bits for pcre_exec()
 
-       The  unused  bits of the options argument for pcre_exec() must be zero.
-       The only bits that may  be  set  are  PCRE_ANCHORED,  PCRE_NEWLINE_xxx,
-       PCRE_NOTBOL,    PCRE_NOTEOL,    PCRE_NOTEMPTY,   PCRE_NOTEMPTY_ATSTART,
-       PCRE_NO_START_OPTIMIZE,  PCRE_NO_UTF8_CHECK,   PCRE_PARTIAL_SOFT,   and
+       The unused bits of the options argument for pcre_exec() must  be  zero.
+       The  only  bits  that  may  be set are PCRE_ANCHORED, PCRE_NEWLINE_xxx,
+       PCRE_NOTBOL,   PCRE_NOTEOL,    PCRE_NOTEMPTY,    PCRE_NOTEMPTY_ATSTART,
+       PCRE_NO_START_OPTIMIZE,   PCRE_NO_UTF8_CHECK,   PCRE_PARTIAL_SOFT,  and
        PCRE_PARTIAL_HARD.
 
          PCRE_ANCHORED
 
-       The  PCRE_ANCHORED  option  limits pcre_exec() to matching at the first
-       matching position. If a pattern was  compiled  with  PCRE_ANCHORED,  or
-       turned  out to be anchored by virtue of its contents, it cannot be made
+       The PCRE_ANCHORED option limits pcre_exec() to matching  at  the  first
+       matching  position.  If  a  pattern was compiled with PCRE_ANCHORED, or
+       turned out to be anchored by virtue of its contents, it cannot be  made
        unachored at matching time.
 
          PCRE_BSR_ANYCRLF
          PCRE_BSR_UNICODE
 
        These options (which are mutually exclusive) control what the \R escape
-       sequence  matches.  The choice is either to match only CR, LF, or CRLF,
-       or to match any Unicode newline sequence. These  options  override  the
+       sequence matches. The choice is either to match only CR, LF,  or  CRLF,
+       or  to  match  any Unicode newline sequence. These options override the
        choice that was made or defaulted when the pattern was compiled.
 
          PCRE_NEWLINE_CR
@@ -1999,94 +2047,129 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
          PCRE_NEWLINE_ANYCRLF
          PCRE_NEWLINE_ANY
 
-       These  options  override  the  newline  definition  that  was chosen or
-       defaulted when the pattern was compiled. For details, see the  descrip-
-       tion  of  pcre_compile()  above.  During  matching,  the newline choice
-       affects the behaviour of the dot, circumflex,  and  dollar  metacharac-
-       ters.  It may also alter the way the match position is advanced after a
+       These options override  the  newline  definition  that  was  chosen  or
+       defaulted  when the pattern was compiled. For details, see the descrip-
+       tion of pcre_compile()  above.  During  matching,  the  newline  choice
+       affects  the  behaviour  of the dot, circumflex, and dollar metacharac-
+       ters. It may also alter the way the match position is advanced after  a
        match failure for an unanchored pattern.
 
-       When PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANYCRLF,  or  PCRE_NEWLINE_ANY  is
-       set,  and a match attempt for an unanchored pattern fails when the cur-
-       rent position is at a  CRLF  sequence,  and  the  pattern  contains  no
-       explicit  matches  for  CR  or  LF  characters,  the  match position is
+       When  PCRE_NEWLINE_CRLF,  PCRE_NEWLINE_ANYCRLF,  or PCRE_NEWLINE_ANY is
+       set, and a match attempt for an unanchored pattern fails when the  cur-
+       rent  position  is  at  a  CRLF  sequence,  and the pattern contains no
+       explicit matches for  CR  or  LF  characters,  the  match  position  is
        advanced by two characters instead of one, in other words, to after the
        CRLF.
 
        The above rule is a compromise that makes the most common cases work as
-       expected. For example, if the  pattern  is  .+A  (and  the  PCRE_DOTALL
+       expected.  For  example,  if  the  pattern  is .+A (and the PCRE_DOTALL
        option is not set), it does not match the string "\r\nA" because, after
-       failing at the start, it skips both the CR and the LF before  retrying.
-       However,  the  pattern  [\r\n]A does match that string, because it con-
+       failing  at the start, it skips both the CR and the LF before retrying.
+       However, the pattern [\r\n]A does match that string,  because  it  con-
        tains an explicit CR or LF reference, and so advances only by one char-
        acter after the first failure.
 
        An explicit match for CR of LF is either a literal appearance of one of
-       those characters, or one of the \r or  \n  escape  sequences.  Implicit
-       matches  such  as [^X] do not count, nor does \s (which includes CR and
+       those  characters,  or  one  of the \r or \n escape sequences. Implicit
+       matches such as [^X] do not count, nor does \s (which includes  CR  and
        LF in the characters that it matches).
 
-       Notwithstanding the above, anomalous effects may still occur when  CRLF
+       Notwithstanding  the above, anomalous effects may still occur when CRLF
        is a valid newline sequence and explicit \r or \n escapes appear in the
        pattern.
 
          PCRE_NOTBOL
 
        This option specifies that first character of the subject string is not
-       the  beginning  of  a  line, so the circumflex metacharacter should not
-       match before it. Setting this without PCRE_MULTILINE (at compile  time)
-       causes  circumflex  never to match. This option affects only the behav-
+       the beginning of a line, so the  circumflex  metacharacter  should  not
+       match  before it. Setting this without PCRE_MULTILINE (at compile time)
+       causes circumflex never to match. This option affects only  the  behav-
        iour of the circumflex metacharacter. It does not affect \A.
 
          PCRE_NOTEOL
 
        This option specifies that the end of the subject string is not the end
-       of  a line, so the dollar metacharacter should not match it nor (except
-       in multiline mode) a newline immediately before it. Setting this  with-
+       of a line, so the dollar metacharacter should not match it nor  (except
+       in  multiline mode) a newline immediately before it. Setting this with-
        out PCRE_MULTILINE (at compile time) causes dollar never to match. This
-       option affects only the behaviour of the dollar metacharacter. It  does
+       option  affects only the behaviour of the dollar metacharacter. It does
        not affect \Z or \z.
 
          PCRE_NOTEMPTY
 
        An empty string is not considered to be a valid match if this option is
-       set. If there are alternatives in the pattern, they are tried.  If  all
-       the  alternatives  match  the empty string, the entire match fails. For
+       set.  If  there are alternatives in the pattern, they are tried. If all
+       the alternatives match the empty string, the entire  match  fails.  For
        example, if the pattern
 
          a?b?
 
-       is applied to a string not beginning with "a" or  "b",  it  matches  an
-       empty  string at the start of the subject. With PCRE_NOTEMPTY set, this
+       is  applied  to  a  string not beginning with "a" or "b", it matches an
+       empty string at the start of the subject. With PCRE_NOTEMPTY set,  this
        match is not valid, so PCRE searches further into the string for occur-
        rences of "a" or "b".
 
          PCRE_NOTEMPTY_ATSTART
 
-       This  is  like PCRE_NOTEMPTY, except that an empty string match that is
-       not at the start of  the  subject  is  permitted.  If  the  pattern  is
+       This is like PCRE_NOTEMPTY, except that an empty string match  that  is
+       not  at  the  start  of  the  subject  is  permitted. If the pattern is
        anchored, such a match can occur only if the pattern contains \K.
 
-       Perl     has    no    direct    equivalent    of    PCRE_NOTEMPTY    or
-       PCRE_NOTEMPTY_ATSTART, but it does make a special  case  of  a  pattern
-       match  of  the empty string within its split() function, and when using
-       the /g modifier. It is  possible  to  emulate  Perl's  behaviour  after
+       Perl    has    no    direct    equivalent    of    PCRE_NOTEMPTY     or
+       PCRE_NOTEMPTY_ATSTART,  but  it  does  make a special case of a pattern
+       match of the empty string within its split() function, and  when  using
+       the  /g  modifier.  It  is  possible  to emulate Perl's behaviour after
        matching a null string by first trying the match again at the same off-
-       set with PCRE_NOTEMPTY_ATSTART and  PCRE_ANCHORED,  and  then  if  that
+       set  with  PCRE_NOTEMPTY_ATSTART  and  PCRE_ANCHORED,  and then if that
        fails, by advancing the starting offset (see below) and trying an ordi-
-       nary match again. There is some code that demonstrates how to  do  this
+       nary  match  again. There is some code that demonstrates how to do this
        in the pcredemo sample program.
 
          PCRE_NO_START_OPTIMIZE
 
-       There  are a number of optimizations that pcre_exec() uses at the start
-       of a match, in order to speed up the process. For  example,  if  it  is
-       known  that  a  match must start with a specific character, it searches
-       the subject for that character, and fails immediately if it cannot find
-       it,  without actually running the main matching function. When callouts
-       are in use, these optimizations can cause  them  to  be  skipped.  This
-       option  disables  the  "start-up" optimizations, causing performance to
-       suffer, but ensuring that the callouts do occur.
+       There are a number of optimizations that pcre_exec() uses at the  start
+       of  a  match,  in  order to speed up the process. For example, if it is
+       known that an unanchored match must start with a specific character, it
+       searches  the  subject  for that character, and fails immediately if it
+       cannot find it, without actually running the  main  matching  function.
+       This means that a special item such as (*COMMIT) at the start of a pat-
+       tern is not considered until after a suitable starting  point  for  the
+       match  has been found. When callouts or (*MARK) items are in use, these
+       "start-up" optimizations can cause them to be skipped if the pattern is
+       never  actually  used.  The start-up optimizations are in effect a pre-
+       scan of the subject that takes place before the pattern is run.
+
+       The PCRE_NO_START_OPTIMIZE option disables the start-up  optimizations,
+       possibly  causing  performance  to  suffer,  but ensuring that in cases
+       where the result is "no match", the callouts do occur, and  that  items
+       such as (*COMMIT) and (*MARK) are considered at every possible starting
+       position in the subject  string.   Setting  PCRE_NO_START_OPTIMIZE  can
+       change the outcome of a matching operation.  Consider the pattern
+
+         (*COMMIT)ABC
+
+       When  this  is  compiled, PCRE records the fact that a match must start
+       with the character "A". Suppose the subject  string  is  "DEFABC".  The
+       start-up  optimization  scans along the subject, finds "A" and runs the
+       first match attempt from there. The (*COMMIT) item means that the  pat-
+       tern  must  match the current starting position, which in this case, it
+       does. However, if the same match  is  run  with  PCRE_NO_START_OPTIMIZE
+       set,  the  initial  scan  along the subject string does not happen. The
+       first match attempt is run starting  from  "D"  and  when  this  fails,
+       (*COMMIT)  prevents  any  further  matches  being tried, so the overall
+       result is "no match". If the pattern is studied,  more  start-up  opti-
+       mizations  may  be  used. For example, a minimum length for the subject
+       may be recorded. Consider the pattern
+
+         (*MARK:A)(X|Y)
+
+       The minimum length for a match is one  character.  If  the  subject  is
+       "ABC",  there  will  be  attempts  to  match "ABC", "BC", "C", and then
+       finally an empty string.  If the pattern is studied, the final  attempt
+       does  not take place, because PCRE knows that the subject is too short,
+       and so the (*MARK) is never encountered.  In this  case,  studying  the
+       pattern  does  not  affect the overall match result, which is still "no
+       match", but it does affect the auxiliary information that is returned.
 
          PCRE_NO_UTF8_CHECK
 
@@ -2273,6 +2356,10 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
        purpose.  If the call via pcre_malloc() fails, this error is given. The
        memory is automatically freed at the end of matching.
 
+       This error is also given if pcre_stack_malloc() fails  in  pcre_exec().
+       This  can happen only when PCRE has been compiled with --disable-stack-
+       for-recursion.
+
          PCRE_ERROR_NOSUBSTRING    (-7)
 
        This error is used by the pcre_copy_substring(),  pcre_get_substring(),
@@ -2584,49 +2671,50 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
        The unused bits of the options argument  for  pcre_dfa_exec()  must  be
        zero.  The  only  bits  that  may  be  set are PCRE_ANCHORED, PCRE_NEW-
        LINE_xxx,        PCRE_NOTBOL,        PCRE_NOTEOL,        PCRE_NOTEMPTY,
-       PCRE_NOTEMPTY_ATSTART, PCRE_NO_UTF8_CHECK, PCRE_PARTIAL_HARD, PCRE_PAR-
-       TIAL_SOFT, PCRE_DFA_SHORTEST, and PCRE_DFA_RESTART. All  but  the  last
-       four  of  these  are  exactly  the  same  as  for pcre_exec(), so their
+       PCRE_NOTEMPTY_ATSTART,       PCRE_NO_UTF8_CHECK,      PCRE_BSR_ANYCRLF,
+       PCRE_BSR_UNICODE, PCRE_NO_START_OPTIMIZE, PCRE_PARTIAL_HARD,  PCRE_PAR-
+       TIAL_SOFT,  PCRE_DFA_SHORTEST,  and PCRE_DFA_RESTART.  All but the last
+       four of these are  exactly  the  same  as  for  pcre_exec(),  so  their
        description is not repeated here.
 
          PCRE_PARTIAL_HARD
          PCRE_PARTIAL_SOFT
 
-       These have the same general effect as they do for pcre_exec(), but  the
-       details  are  slightly  different.  When  PCRE_PARTIAL_HARD  is set for
-       pcre_dfa_exec(), it returns PCRE_ERROR_PARTIAL if the end of  the  sub-
-       ject  is  reached  and there is still at least one matching possibility
+       These  have the same general effect as they do for pcre_exec(), but the
+       details are slightly  different.  When  PCRE_PARTIAL_HARD  is  set  for
+       pcre_dfa_exec(),  it  returns PCRE_ERROR_PARTIAL if the end of the sub-
+       ject is reached and there is still at least  one  matching  possibility
        that requires additional characters. This happens even if some complete
        matches have also been found. When PCRE_PARTIAL_SOFT is set, the return
        code PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if the end
-       of  the  subject  is  reached, there have been no complete matches, but
-       there is still at least one matching possibility. The  portion  of  the
-       string  that  was inspected when the longest partial match was found is
+       of the subject is reached, there have been  no  complete  matches,  but
+       there  is  still  at least one matching possibility. The portion of the
+       string that was inspected when the longest partial match was  found  is
        set as the first matching string in both cases.
 
          PCRE_DFA_SHORTEST
 
-       Setting the PCRE_DFA_SHORTEST option causes the matching  algorithm  to
+       Setting  the  PCRE_DFA_SHORTEST option causes the matching algorithm to
        stop as soon as it has found one match. Because of the way the alterna-
-       tive algorithm works, this is necessarily the shortest  possible  match
+       tive  algorithm  works, this is necessarily the shortest possible match
        at the first possible matching point in the subject string.
 
          PCRE_DFA_RESTART
 
        When pcre_dfa_exec() returns a partial match, it is possible to call it
-       again, with additional subject characters, and have  it  continue  with
-       the  same match. The PCRE_DFA_RESTART option requests this action; when
-       it is set, the workspace and wscount options must  reference  the  same
-       vector  as  before  because data about the match so far is left in them
+       again,  with  additional  subject characters, and have it continue with
+       the same match. The PCRE_DFA_RESTART option requests this action;  when
+       it  is  set,  the workspace and wscount options must reference the same
+       vector as before because data about the match so far is  left  in  them
        after a partial match. There is more discussion of this facility in the
        pcrepartial documentation.
 
    Successful returns from pcre_dfa_exec()
 
-       When  pcre_dfa_exec()  succeeds, it may have matched more than one sub-
+       When pcre_dfa_exec() succeeds, it may have matched more than  one  sub-
        string in the subject. Note, however, that all the matches from one run
-       of  the  function  start  at the same point in the subject. The shorter
-       matches are all initial substrings of the longer matches. For  example,
+       of the function start at the same point in  the  subject.  The  shorter
+       matches  are all initial substrings of the longer matches. For example,
        if the pattern
 
          <.*>
@@ -2641,61 +2729,61 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
          <something> <something else>
          <something> <something else> <something further>
 
-       On  success,  the  yield of the function is a number greater than zero,
-       which is the number of matched substrings.  The  substrings  themselves
-       are  returned  in  ovector. Each string uses two elements; the first is
-       the offset to the start, and the second is the offset to  the  end.  In
-       fact,  all  the  strings  have the same start offset. (Space could have
-       been saved by giving this only once, but it was decided to retain  some
-       compatibility  with  the  way pcre_exec() returns data, even though the
+       On success, the yield of the function is a number  greater  than  zero,
+       which  is  the  number of matched substrings. The substrings themselves
+       are returned in ovector. Each string uses two elements;  the  first  is
+       the  offset  to  the start, and the second is the offset to the end. In
+       fact, all the strings have the same start  offset.  (Space  could  have
+       been  saved by giving this only once, but it was decided to retain some
+       compatibility with the way pcre_exec() returns data,  even  though  the
        meaning of the strings is different.)
 
        The strings are returned in reverse order of length; that is, the long-
-       est  matching  string is given first. If there were too many matches to
-       fit into ovector, the yield of the function is zero, and the vector  is
+       est matching string is given first. If there were too many  matches  to
+       fit  into ovector, the yield of the function is zero, and the vector is
        filled with the longest matches.
 
    Error returns from pcre_dfa_exec()
 
-       The  pcre_dfa_exec()  function returns a negative number when it fails.
-       Many of the errors are the same  as  for  pcre_exec(),  and  these  are
-       described  above.   There are in addition the following errors that are
+       The pcre_dfa_exec() function returns a negative number when  it  fails.
+       Many  of  the  errors  are  the  same as for pcre_exec(), and these are
+       described above.  There are in addition the following errors  that  are
        specific to pcre_dfa_exec():
 
          PCRE_ERROR_DFA_UITEM      (-16)
 
-       This return is given if pcre_dfa_exec() encounters an item in the  pat-
-       tern  that  it  does not support, for instance, the use of \C or a back
+       This  return is given if pcre_dfa_exec() encounters an item in the pat-
+       tern that it does not support, for instance, the use of \C  or  a  back
        reference.
 
          PCRE_ERROR_DFA_UCOND      (-17)
 
-       This return is given if pcre_dfa_exec()  encounters  a  condition  item
-       that  uses  a back reference for the condition, or a test for recursion
+       This  return  is  given  if pcre_dfa_exec() encounters a condition item
+       that uses a back reference for the condition, or a test  for  recursion
        in a specific group. These are not supported.
 
          PCRE_ERROR_DFA_UMLIMIT    (-18)
 
-       This return is given if pcre_dfa_exec() is called with an  extra  block
+       This  return  is given if pcre_dfa_exec() is called with an extra block
        that contains a setting of the match_limit field. This is not supported
        (it is meaningless).
 
          PCRE_ERROR_DFA_WSSIZE     (-19)
 
-       This return is given if  pcre_dfa_exec()  runs  out  of  space  in  the
+       This  return  is  given  if  pcre_dfa_exec()  runs  out of space in the
        workspace vector.
 
          PCRE_ERROR_DFA_RECURSE    (-20)
 
-       When  a  recursive subpattern is processed, the matching function calls
-       itself recursively, using private vectors for  ovector  and  workspace.
-       This  error  is  given  if  the output vector is not large enough. This
+       When a recursive subpattern is processed, the matching  function  calls
+       itself  recursively,  using  private vectors for ovector and workspace.
+       This error is given if the output vector  is  not  large  enough.  This
        should be extremely rare, as a vector of size 1000 is used.
 
 
 SEE ALSO
 
-       pcrebuild(3), pcrecallout(3), pcrecpp(3)(3), pcrematching(3),  pcrepar-
+       pcrebuild(3),  pcrecallout(3), pcrecpp(3)(3), pcrematching(3), pcrepar-
        tial(3), pcreposix(3), pcreprecompile(3), pcresample(3), pcrestack(3).
 
 
@@ -2708,8 +2796,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 03 October 2009
-       Copyright (c) 1997-2009 University of Cambridge.
+       Last updated: 21 June 2010
+       Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
 
@@ -2905,7 +2993,7 @@ DIFFERENCES BETWEEN PCRE AND PERL
 
        This  document describes the differences in the ways that PCRE and Perl
        handle regular expressions. The differences  described  here  are  with
-       respect to Perl 5.10.
+       respect to Perl 5.10/5.11.
 
        1.  PCRE has only a subset of Perl's UTF-8 and Unicode support. Details
        of what it does have are given in the section on UTF-8 support  in  the
@@ -2976,11 +3064,7 @@ DIFFERENCES BETWEEN PCRE AND PERL
        matching "aba" against the  pattern  /^(a(b)?)+$/  in  Perl  leaves  $2
        unset, but in PCRE it is set to "b".
 
-       11.  PCRE  does  support  Perl  5.10's  backtracking  verbs  (*ACCEPT),
-       (*FAIL), (*F), (*COMMIT), (*PRUNE), (*SKIP), and (*THEN), but  only  in
-       the forms without an argument. PCRE does not support (*MARK).
-
-       12.  PCRE's handling of duplicate subpattern numbers and duplicate sub-
+       11.  PCRE's handling of duplicate subpattern numbers and duplicate sub-
        pattern names is not as general as Perl's. This is a consequence of the
        fact the PCRE works internally just with numbers, using an external ta-
        ble to translate between numbers and names. In  particular,  a  pattern
@@ -2991,7 +3075,7 @@ DIFFERENCES BETWEEN PCRE AND PERL
        turing subpattern number 1. To avoid this confusing situation, an error
        is given at compile time.
 
-       13. PCRE provides some extensions to the Perl regular expression facil-
+       12. PCRE provides some extensions to the Perl regular expression facil-
        ities.   Perl  5.10  includes new features that are not in earlier ver-
        sions of Perl, some of which (such as named parentheses) have  been  in
        PCRE for some time. This list is with respect to Perl 5.10:
@@ -3046,8 +3130,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 04 October 2009
-       Copyright (c) 1997-2009 University of Cambridge.
+       Last updated: 12 May 2010
+       Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
 
@@ -3089,6 +3173,16 @@ PCRE REGULAR EXPRESSION DETAILS
        below.  There  is  also  a  summary of UTF-8 features in the section on
        UTF-8 support in the main pcre page.
 
+       Another special sequence that may appear at the start of a  pattern  or
+       in combination with (*UTF8) is:
+
+         (*UCP)
+
+       This  has  the  same  effect  as setting the PCRE_UCP option: it causes
+       sequences such as \d and \w to  use  Unicode  properties  to  determine
+       character types, instead of recognizing only characters with codes less
+       than 128 via a lookup table.
+
        The remainder of this document discusses the  patterns  that  are  sup-
        ported  by  PCRE when its main matching function, pcre_exec(), is used.
        From  release  6.0,   PCRE   offers   a   second   matching   function,
@@ -3129,11 +3223,13 @@ NEWLINE CONVENTIONS
        and that they must be in upper case.  If  more  than  one  of  them  is
        present, the last one is used.
 
-       The  newline  convention  does  not  affect what the \R escape sequence
-       matches. By default, this is any Unicode  newline  sequence,  for  Perl
-       compatibility.  However, this can be changed; see the description of \R
-       in the section entitled "Newline sequences" below. A change of \R  set-
-       ting can be combined with a change of newline convention.
+       The  newline convention affects the interpretation of the dot metachar-
+       acter when PCRE_DOTALL is not set, and also the behaviour of  \N.  How-
+       ever,  it  does  not  affect  what  the  \R escape sequence matches. By
+       default, this is any Unicode newline sequence, for Perl  compatibility.
+       However,  this can be changed; see the description of \R in the section
+       entitled "Newline sequences" below. A change of \R setting can be  com-
+       bined with a change of newline convention.
 
 
 CHARACTERS AND METACHARACTERS
@@ -3315,9 +3411,11 @@ BACKSLASH
        All the sequences that define a single character value can be used both
        inside  and  outside character classes. In addition, inside a character
        class, the sequence \b is interpreted as the backspace  character  (hex
-       08),  and the sequences \R and \X are interpreted as the characters "R"
-       and "X", respectively. Outside a character class, these sequences  have
-       different meanings (see below).
+       08).  The sequences \B, \N, \R, and \X are not special inside a charac-
+       ter class. Like any  other  unrecognized  escape  sequences,  they  are
+       treated  as  the  literal characters "B", "N", "R", and "X" by default,
+       but cause an error if the PCRE_EXTRA option is set. Outside a character
+       class, these sequences have different meanings.
 
    Absolute and relative back references
 
@@ -3337,8 +3435,7 @@ BACKSLASH
 
    Generic character types
 
-       Another use of backslash is for specifying generic character types. The
-       following are always recognized:
+       Another use of backslash is for specifying generic character types:
 
          \d     any decimal digit
          \D     any character that is not a decimal digit
@@ -3351,14 +3448,17 @@ BACKSLASH
          \w     any "word" character
          \W     any "non-word" character
 
-       Each pair of escape sequences partitions the complete set of characters
-       into  two disjoint sets. Any given character matches one, and only one,
-       of each pair.
+       There is also the single sequence \N, which matches a non-newline char-
+       acter.  This is the same as the "." metacharacter when  PCRE_DOTALL  is
+       not set.
 
-       These character type sequences can appear both inside and outside char-
-       acter  classes.  They each match one character of the appropriate type.
-       If the current matching point is at the end of the subject string,  all
-       of them fail, since there is no character to match.
+       Each  pair of lower and upper case escape sequences partitions the com-
+       plete set of characters into two disjoint  sets.  Any  given  character
+       matches  one, and only one, of each pair. The sequences can appear both
+       inside and outside character classes. They each match one character  of
+       the  appropriate  type.  If the current matching point is at the end of
+       the subject string, all of them fail, because there is no character  to
+       match.
 
        For  compatibility  with Perl, \s does not match the VT character (code
        11).  This makes it different from the the POSIX "space" class. The  \s
@@ -3366,16 +3466,37 @@ BACKSLASH
        "use locale;" is included in a Perl script, \s may match the VT charac-
        ter. In PCRE, it never does.
 
-       In  UTF-8 mode, characters with values greater than 128 never match \d,
-       \s, or \w, and always match \D, \S, and \W. This is true even when Uni-
-       code  character  property  support is available. These sequences retain
-       their original meanings from before UTF-8 support was available, mainly
-       for  efficiency  reasons. Note that this also affects \b, because it is
-       defined in terms of \w and \W.
+       A  "word"  character is an underscore or any character that is a letter
+       or digit.  By default, the definition of letters  and  digits  is  con-
+       trolled  by PCRE's low-valued character tables, and may vary if locale-
+       specific matching is taking place (see "Locale support" in the  pcreapi
+       page).  For  example,  in  a French locale such as "fr_FR" in Unix-like
+       systems, or "french" in Windows, some character codes greater than  128
+       are  used  for  accented letters, and these are then matched by \w. The
+       use of locales with Unicode is discouraged.
+
+       By default, in UTF-8 mode, characters  with  values  greater  than  128
+       never  match  \d,  \s,  or  \w,  and always match \D, \S, and \W. These
+       sequences retain their original meanings from before UTF-8 support  was
+       available,  mainly for efficiency reasons. However, if PCRE is compiled
+       with Unicode property support, and the PCRE_UCP option is set, the  be-
+       haviour  is  changed  so  that Unicode properties are used to determine
+       character types, as follows:
+
+         \d  any character that \p{Nd} matches (decimal digit)
+         \s  any character that \p{Z} matches, plus HT, LF, FF, CR
+         \w  any character that \p{L} or \p{N} matches, plus underscore
+
+       The upper case escapes match the inverse sets of characters. Note  that
+       \d  matches  only decimal digits, whereas \w matches any Unicode digit,
+       as well as any Unicode letter, and underscore. Note also that  PCRE_UCP
+       affects  \b,  and  \B  because  they are defined in terms of \w and \W.
+       Matching these sequences is noticeably slower when PCRE_UCP is set.
 
        The sequences \h, \H, \v, and \V are Perl 5.10 features. In contrast to
-       the  other  sequences, these do match certain high-valued codepoints in
-       UTF-8 mode.  The horizontal space characters are:
+       the  other  sequences,  which  match  only ASCII characters by default,
+       these always  match  certain  high-valued  codepoints  in  UTF-8  mode,
+       whether or not PCRE_UCP is set. The horizontal space characters are:
 
          U+0009     Horizontal tab
          U+0020     Space
@@ -3407,15 +3528,6 @@ BACKSLASH
          U+2028     Line separator
          U+2029     Paragraph separator
 
-       A "word" character is an underscore or any character less than 256 that
-       is  a  letter  or  digit.  The definition of letters and digits is con-
-       trolled by PCRE's low-valued character tables, and may vary if  locale-
-       specific  matching is taking place (see "Locale support" in the pcreapi
-       page). For example, in a French locale such  as  "fr_FR"  in  Unix-like
-       systems,  or "french" in Windows, some character codes greater than 128
-       are used for accented letters, and these are matched by \w. The use  of
-       locales with Unicode is discouraged.
-
    Newline sequences
 
        Outside  a  character class, by default, the escape sequence \R matches
@@ -3454,29 +3566,33 @@ BACKSLASH
        are  not  Perl-compatible,  are  recognized only at the very start of a
        pattern, and that they must be in upper case. If more than one of  them
        is present, the last one is used. They can be combined with a change of
-       newline convention, for example, a pattern can start with:
+       newline convention; for example, a pattern can start with:
 
          (*ANY)(*BSR_ANYCRLF)
 
-       Inside a character class, \R matches the letter "R".
+       They can also be combined with the (*UTF8) or (*UCP) special sequences.
+       Inside  a  character  class,  \R  is  treated as an unrecognized escape
+       sequence, and so matches the letter "R" by default, but causes an error
+       if PCRE_EXTRA is set.
 
    Unicode character properties
 
        When PCRE is built with Unicode character property support, three addi-
-       tional  escape sequences that match characters with specific properties
-       are available.  When not in UTF-8 mode, these sequences are  of  course
-       limited  to  testing characters whose codepoints are less than 256, but
+       tional escape sequences that match characters with specific  properties
+       are  available.   When not in UTF-8 mode, these sequences are of course
+       limited to testing characters whose codepoints are less than  256,  but
        they do work in this mode.  The extra escape sequences are:
 
          \p{xx}   a character with the xx property
          \P{xx}   a character without the xx property
          \X       an extended Unicode sequence
 
-       The property names represented by xx above are limited to  the  Unicode
-       script names, the general category properties, and "Any", which matches
-       any character (including newline). Other properties such as "InMusical-
-       Symbols"  are  not  currently supported by PCRE. Note that \P{Any} does
-       not match any characters, so always causes a match failure.
+       The  property  names represented by xx above are limited to the Unicode
+       script names, the general category properties, "Any", which matches any
+       character   (including  newline),  and  some  special  PCRE  properties
+       (described in the next section).  Other Perl properties such as  "InMu-
+       sicalSymbols"  are  not  currently supported by PCRE. Note that \P{Any}
+       does not match any characters, so always causes a match failure.
 
        Sets of Unicode characters are defined as belonging to certain scripts.
        A  character from one of these sets can be matched using a script name.
@@ -3503,14 +3619,15 @@ BACKSLASH
        Tai_Tham,  Tai_Viet,  Tamil,  Telugu,  Thaana, Thai, Tibetan, Tifinagh,
        Ugaritic, Vai, Yi.
 
-       Each character has exactly one general category property, specified  by
-       a two-letter abbreviation. For compatibility with Perl, negation can be
-       specified by including a circumflex between the opening brace  and  the
-       property name. For example, \p{^Lu} is the same as \P{Lu}.
+       Each character has exactly one Unicode general category property, spec-
+       ified  by a two-letter abbreviation. For compatibility with Perl, nega-
+       tion can be specified by including a  circumflex  between  the  opening
+       brace  and  the  property  name.  For  example,  \p{^Lu} is the same as
+       \P{Lu}.
 
        If only one letter is specified with \p or \P, it includes all the gen-
-       eral category properties that start with that letter. In this case,  in
-       the  absence of negation, the curly brackets in the escape sequence are
+       eral  category properties that start with that letter. In this case, in
+       the absence of negation, the curly brackets in the escape sequence  are
        optional; these two examples have the same effect:
 
          \p{L}
@@ -3562,73 +3679,94 @@ BACKSLASH
          Zp    Paragraph separator
          Zs    Space separator
 
-       The special property L& is also supported: it matches a character  that
-       has  the  Lu,  Ll, or Lt property, in other words, a letter that is not
+       The  special property L& is also supported: it matches a character that
+       has the Lu, Ll, or Lt property, in other words, a letter  that  is  not
        classified as a modifier or "other".
 
-       The Cs (Surrogate) property applies only to  characters  in  the  range
-       U+D800  to  U+DFFF. Such characters are not valid in UTF-8 strings (see
+       The  Cs  (Surrogate)  property  applies only to characters in the range
+       U+D800 to U+DFFF. Such characters are not valid in UTF-8  strings  (see
        RFC 3629) and so cannot be tested by PCRE, unless UTF-8 validity check-
-       ing  has  been  turned off (see the discussion of PCRE_NO_UTF8_CHECK in
+       ing has been turned off (see the discussion  of  PCRE_NO_UTF8_CHECK  in
        the pcreapi page). Perl does not support the Cs property.
 
-       The long synonyms for  property  names  that  Perl  supports  (such  as
-       \p{Letter})  are  not  supported by PCRE, nor is it permitted to prefix
+       The  long  synonyms  for  property  names  that  Perl supports (such as
+       \p{Letter}) are not supported by PCRE, nor is it  permitted  to  prefix
        any of these properties with "Is".
 
        No character that is in the Unicode table has the Cn (unassigned) prop-
        erty.  Instead, this property is assumed for any code point that is not
        in the Unicode table.
 
-       Specifying caseless matching does not affect  these  escape  sequences.
+       Specifying  caseless  matching  does not affect these escape sequences.
        For example, \p{Lu} always matches only upper case letters.
 
-       The  \X  escape  matches  any number of Unicode characters that form an
+       The \X escape matches any number of Unicode  characters  that  form  an
        extended Unicode sequence. \X is equivalent to
 
          (?>\PM\pM*)
 
-       That is, it matches a character without the "mark"  property,  followed
-       by  zero  or  more  characters with the "mark" property, and treats the
-       sequence as an atomic group (see below).  Characters  with  the  "mark"
-       property  are  typically  accents  that affect the preceding character.
-       None of them have codepoints less than 256, so  in  non-UTF-8  mode  \X
+       That  is,  it matches a character without the "mark" property, followed
+       by zero or more characters with the "mark"  property,  and  treats  the
+       sequence  as  an  atomic group (see below).  Characters with the "mark"
+       property are typically accents that  affect  the  preceding  character.
+       None  of  them  have  codepoints less than 256, so in non-UTF-8 mode \X
        matches any one character.
 
-       Matching  characters  by Unicode property is not fast, because PCRE has
-       to search a structure that contains  data  for  over  fifteen  thousand
+       Matching characters by Unicode property is not fast, because  PCRE  has
+       to  search  a  structure  that  contains data for over fifteen thousand
        characters. That is why the traditional escape sequences such as \d and
-       \w do not use Unicode properties in PCRE.
+       \w  do  not  use  Unicode properties in PCRE by default, though you can
+       make them do so by setting the PCRE_UCP option for pcre_compile() or by
+       starting the pattern with (*UCP).
+
+   PCRE's additional properties
+
+       As  well  as  the standard Unicode properties described in the previous
+       section, PCRE supports four more that make it possible to convert  tra-
+       ditional escape sequences such as \w and \s and POSIX character classes
+       to use Unicode properties. PCRE uses these non-standard, non-Perl prop-
+       erties internally when PCRE_UCP is set. They are:
+
+         Xan   Any alphanumeric character
+         Xps   Any POSIX space character
+         Xsp   Any Perl space character
+         Xwd   Any Perl "word" character
+
+       Xan  matches  characters that have either the L (letter) or the N (num-
+       ber) property. Xps matches the characters tab, linefeed, vertical  tab,
+       formfeed,  or  carriage  return, and any other character that has the Z
+       (separator) property.  Xsp is the same as Xps, except that vertical tab
+       is excluded. Xwd matches the same characters as Xan, plus underscore.
 
    Resetting the match start
 
        The escape sequence \K, which is a Perl 5.10 feature, causes any previ-
-       ously  matched  characters  not  to  be  included  in the final matched
+       ously matched characters not  to  be  included  in  the  final  matched
        sequence. For example, the pattern:
 
          foo\Kbar
 
-       matches "foobar", but reports that it has matched "bar".  This  feature
-       is  similar  to  a lookbehind assertion (described below).  However, in
-       this case, the part of the subject before the real match does not  have
-       to  be of fixed length, as lookbehind assertions do. The use of \K does
-       not interfere with the setting of captured  substrings.   For  example,
+       matches  "foobar",  but reports that it has matched "bar". This feature
+       is similar to a lookbehind assertion (described  below).   However,  in
+       this  case, the part of the subject before the real match does not have
+       to be of fixed length, as lookbehind assertions do. The use of \K  does
+       not  interfere  with  the setting of captured substrings.  For example,
        when the pattern
 
          (foo)\Kbar
 
        matches "foobar", the first substring is still set to "foo".
 
-       Perl  documents  that  the  use  of  \K  within assertions is "not well
-       defined". In PCRE, \K is acted upon  when  it  occurs  inside  positive
+       Perl documents that the use  of  \K  within  assertions  is  "not  well
+       defined".  In  PCRE,  \K  is  acted upon when it occurs inside positive
        assertions, but is ignored in negative assertions.
 
    Simple assertions
 
-       The  final use of backslash is for certain simple assertions. An asser-
-       tion specifies a condition that has to be met at a particular point  in
-       a  match, without consuming any characters from the subject string. The
-       use of subpatterns for more complicated assertions is described  below.
+       The final use of backslash is for certain simple assertions. An  asser-
+       tion  specifies a condition that has to be met at a particular point in
+       a match, without consuming any characters from the subject string.  The
+       use  of subpatterns for more complicated assertions is described below.
        The backslashed assertions are:
 
          \b     matches at a word boundary
@@ -3639,15 +3777,20 @@ BACKSLASH
          \z     matches only at the end of the subject
          \G     matches at the first matching position in the subject
 
-       These  assertions may not appear in character classes (but note that \b
-       has a different meaning, namely the backspace character, inside a char-
-       acter class).
+       Inside a character class, \b has a different meaning;  it  matches  the
+       backspace  character.  If  any  other  of these assertions appears in a
+       character class, by default it matches the corresponding literal  char-
+       acter  (for  example,  \B  matches  the  letter  B).  However,  if  the
+       PCRE_EXTRA option is set, an "invalid escape sequence" error is  gener-
+       ated instead.
 
        A  word  boundary is a position in the subject string where the current
        character and the previous character do not both match \w or  \W  (i.e.
        one  matches  \w  and the other matches \W), or the start or end of the
-       string if the first or last character matches \w, respectively. Neither
-       PCRE  nor  Perl  has a separte "start of word" or "end of word" metase-
+       string if the first or last  character  matches  \w,  respectively.  In
+       UTF-8  mode,  the  meanings  of \w and \W can be changed by setting the
+       PCRE_UCP option. When this is done, it also affects \b and \B.  Neither
+       PCRE  nor  Perl has a separate "start of word" or "end of word" metase-
        quence. However, whatever follows \b normally determines which  it  is.
        For example, the fragment \ba matches "a" at the start of a word.
 
@@ -3732,7 +3875,7 @@ CIRCUMFLEX AND DOLLAR
        set.
 
 
-FULL STOP (PERIOD, DOT)
+FULL STOP (PERIOD, DOT) AND \N
 
        Outside a character class, a dot in the pattern matches any one charac-
        ter  in  the subject string except (by default) a character that signi-
@@ -3755,6 +3898,10 @@ FULL STOP (PERIOD, DOT)
        flex and dollar, the only relationship being  that  they  both  involve
        newlines. Dot has no special meaning in a character class.
 
+       The escape sequence \N always behaves as a dot does when PCRE_DOTALL is
+       not set. In other words, it matches any one character except  one  that
+       signifies the end of a line.
+
 
 MATCHING A SINGLE BYTE
 
@@ -3848,13 +3995,13 @@ SQUARE BRACKETS AND CHARACTER CLASSES
        concept  of  case for characters with values greater than 128 only when
        it is compiled with Unicode property support.
 
-       The character types \d, \D, \p, \P, \s, \S, \w, and \W may also  appear
-       in  a  character  class,  and add the characters that they match to the
-       class. For example, [\dABCDEF] matches any hexadecimal digit. A circum-
-       flex  can  conveniently  be used with the upper case character types to
-       specify a more restricted set of characters  than  the  matching  lower
-       case  type.  For example, the class [^\W_] matches any letter or digit,
-       but not underscore.
+       The character types \d, \D, \h, \H, \p, \P, \s, \S, \v, \V, \w, and  \W
+       may  also appear in a character class, and add the characters that they
+       match to the class. For example,  [\dABCDEF]  matches  any  hexadecimal
+       digit.  A circumflex can conveniently be used with the upper case char-
+       acter types to specify a more restricted set  of  characters  than  the
+       matching  lower  case  type.  For example, the class [^\W_] matches any
+       letter or digit, but not underscore.
 
        The only metacharacters that are recognized in  character  classes  are
        backslash,  hyphen  (only  where  it can be interpreted as specifying a
@@ -3873,7 +4020,7 @@ POSIX CHARACTER CLASSES
          [01[:alpha:]%]
 
        matches "0", "1", any alphabetic character, or "%". The supported class
-       names are
+       names are:
 
          alnum    letters and digits
          alpha    letters
@@ -3884,7 +4031,7 @@ POSIX CHARACTER CLASSES
          graph    printing characters, excluding space
          lower    lower case letters
          print    printing characters, including space
-         punct    printing characters, excluding letters and digits
+         punct    printing characters, excluding letters and digits and space
          space    white space (not quite the same as \s)
          upper    upper case letters
          word     "word" characters (same as \w)
@@ -3905,30 +4052,46 @@ POSIX CHARACTER CLASSES
        POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but
        these are not supported, and an error is given if they are encountered.
 
-       In UTF-8 mode, characters with values greater than 128 do not match any
-       of the POSIX character classes.
+       By  default,  in UTF-8 mode, characters with values greater than 128 do
+       not match any of the POSIX character classes. However, if the  PCRE_UCP
+       option  is passed to pcre_compile(), some of the classes are changed so
+       that Unicode character properties are used. This is achieved by replac-
+       ing the POSIX classes by other sequences, as follows:
+
+         [:alnum:]  becomes  \p{Xan}
+         [:alpha:]  becomes  \p{L}
+         [:blank:]  becomes  \h
+         [:digit:]  becomes  \p{Nd}
+         [:lower:]  becomes  \p{Ll}
+         [:space:]  becomes  \p{Xps}
+         [:upper:]  becomes  \p{Lu}
+         [:word:]   becomes  \p{Xwd}
+
+       Negated  versions,  such  as [:^alpha:] use \P instead of \p. The other
+       POSIX classes are unchanged, and match only characters with code points
+       less than 128.
 
 
 VERTICAL BAR
 
-       Vertical bar characters are used to separate alternative patterns.  For
+       Vertical  bar characters are used to separate alternative patterns. For
        example, the pattern
 
          gilbert|sullivan
 
-       matches  either "gilbert" or "sullivan". Any number of alternatives may
-       appear, and an empty  alternative  is  permitted  (matching  the  empty
+       matches either "gilbert" or "sullivan". Any number of alternatives  may
+       appear,  and  an  empty  alternative  is  permitted (matching the empty
        string). The matching process tries each alternative in turn, from left
-       to right, and the first one that succeeds is used. If the  alternatives
-       are  within a subpattern (defined below), "succeeds" means matching the
+       to  right, and the first one that succeeds is used. If the alternatives
+       are within a subpattern (defined below), "succeeds" means matching  the
        rest of the main pattern as well as the alternative in the subpattern.
 
 
 INTERNAL OPTION SETTING
 
-       The settings of the  PCRE_CASELESS,  PCRE_MULTILINE,  PCRE_DOTALL,  and
-       PCRE_EXTENDED  options  (which are Perl-compatible) can be changed from
-       within the pattern by  a  sequence  of  Perl  option  letters  enclosed
+       The  settings  of  the  PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and
+       PCRE_EXTENDED options (which are Perl-compatible) can be  changed  from
+       within  the  pattern  by  a  sequence  of  Perl option letters enclosed
        between "(?" and ")".  The option letters are
 
          i  for PCRE_CASELESS
@@ -3938,47 +4101,48 @@ INTERNAL OPTION SETTING
 
        For example, (?im) sets caseless, multiline matching. It is also possi-
        ble to unset these options by preceding the letter with a hyphen, and a
-       combined  setting and unsetting such as (?im-sx), which sets PCRE_CASE-
-       LESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and  PCRE_EXTENDED,
-       is  also  permitted.  If  a  letter  appears  both before and after the
+       combined setting and unsetting such as (?im-sx), which sets  PCRE_CASE-
+       LESS  and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED,
+       is also permitted. If a  letter  appears  both  before  and  after  the
        hyphen, the option is unset.
 
-       The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and  PCRE_EXTRA
-       can  be changed in the same way as the Perl-compatible options by using
+       The  PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA
+       can be changed in the same way as the Perl-compatible options by  using
        the characters J, U and X respectively.
 
-       When one of these option changes occurs at  top  level  (that  is,  not
-       inside  subpattern parentheses), the change applies to the remainder of
+       When  one  of  these  option  changes occurs at top level (that is, not
+       inside subpattern parentheses), the change applies to the remainder  of
        the pattern that follows. If the change is placed right at the start of
        a pattern, PCRE extracts it into the global options (and it will there-
        fore show up in data extracted by the pcre_fullinfo() function).
 
-       An option change within a subpattern (see below for  a  description  of
+       An  option  change  within a subpattern (see below for a description of
        subpatterns) affects only that part of the current pattern that follows
        it, so
 
          (a(?i)b)c
 
        matches abc and aBc and no other strings (assuming PCRE_CASELESS is not
-       used).   By  this means, options can be made to have different settings
-       in different parts of the pattern. Any changes made in one  alternative
-       do  carry  on  into subsequent branches within the same subpattern. For
+       used).  By this means, options can be made to have  different  settings
+       in  different parts of the pattern. Any changes made in one alternative
+       do carry on into subsequent branches within the  same  subpattern.  For
        example,
 
          (a(?i)b|c)
 
-       matches "ab", "aB", "c", and "C", even though  when  matching  "C"  the
-       first  branch  is  abandoned before the option setting. This is because
-       the effects of option settings happen at compile time. There  would  be
+       matches  "ab",  "aB",  "c",  and "C", even though when matching "C" the
+       first branch is abandoned before the option setting.  This  is  because
+       the  effects  of option settings happen at compile time. There would be
        some very weird behaviour otherwise.
 
-       Note:  There  are  other  PCRE-specific  options that can be set by the
-       application when the compile or match functions  are  called.  In  some
+       Note: There are other PCRE-specific options that  can  be  set  by  the
+       application  when  the  compile  or match functions are called. In some
        cases the pattern can contain special leading sequences such as (*CRLF)
-       to override what the application has set or what  has  been  defaulted.
-       Details  are  given  in the section entitled "Newline sequences" above.
-       There is also the (*UTF8) leading sequence that  can  be  used  to  set
-       UTF-8 mode; this is equivalent to setting the PCRE_UTF8 option.
+       to  override  what  the application has set or what has been defaulted.
+       Details are given in the section entitled  "Newline  sequences"  above.
+       There  are  also  the  (*UTF8) and (*UCP) leading sequences that can be
+       used to set UTF-8 and Unicode property modes; they  are  equivalent  to
+       setting the PCRE_UTF8 and the PCRE_UCP options, respectively.
 
 
 SUBPATTERNS
@@ -5144,14 +5308,26 @@ BACKTRACKING CONTROL
        tested.
 
        The  new verbs make use of what was previously invalid syntax: an open-
-       ing parenthesis followed by an asterisk. In Perl, they are generally of
-       the form (*VERB:ARG) but PCRE does not support the use of arguments, so
-       its general form is just (*VERB). Any number of these verbs  may  occur
-       in a pattern. There are two kinds:
+       ing parenthesis followed by an asterisk. They are generally of the form
+       (*VERB)  or (*VERB:NAME). Some may take either form, with differing be-
+       haviour, depending on whether or not an argument is present. An name is
+       a  sequence  of letters, digits, and underscores. If the name is empty,
+       that is, if the closing parenthesis immediately follows the colon,  the
+       effect is as if the colon were not there. Any number of these verbs may
+       occur in a pattern.
+
+       PCRE contains some optimizations that are used to speed up matching  by
+       running some checks at the start of each match attempt. For example, it
+       may know the minimum length of matching subject, or that  a  particular
+       character  must  be present. When one of these optimizations suppresses
+       the running of a match, any included backtracking verbs  will  not,  of
+       course, be processed. You can suppress the start-of-match optimizations
+       by setting the PCRE_NO_START_OPTIMIZE option when calling pcre_exec().
 
    Verbs that act immediately
 
-       The following verbs act as soon as they are encountered:
+       The following verbs act as soon as they are encountered. They  may  not
+       be followed by a name.
 
           (*ACCEPT)
 
@@ -5180,70 +5356,174 @@ BACKTRACKING CONTROL
        A  match  with the string "aaaa" always fails, but the callout is taken
        before each backtrack happens (in this example, 10 times).
 
+   Recording which path was taken
+
+       There is one verb whose main purpose  is  to  track  how  a  match  was
+       arrived  at,  though  it  also  has a secondary use in conjunction with
+       advancing the match starting point (see (*SKIP) below).
+
+         (*MARK:NAME) or (*:NAME)
+
+       A name is always  required  with  this  verb.  There  may  be  as  many
+       instances  of  (*MARK) as you like in a pattern, and their names do not
+       have to be unique.
+
+       When a match succeeds, the name  of  the  last-encountered  (*MARK)  is
+       passed  back  to  the  caller  via  the  pcre_extra  data structure, as
+       described in the section on pcre_extra in the pcreapi documentation. No
+       data  is  returned  for a partial match. Here is an example of pcretest
+       output, where the /K modifier requests the retrieval and outputting  of
+       (*MARK) data:
+
+         /X(*MARK:A)Y|X(*MARK:B)Z/K
+         XY
+          0: XY
+         MK: A
+         XZ
+          0: XZ
+         MK: B
+
+       The (*MARK) name is tagged with "MK:" in this output, and in this exam-
+       ple it indicates which of the two alternatives matched. This is a  more
+       efficient  way of obtaining this information than putting each alterna-
+       tive in its own capturing parentheses.
+
+       A name may also be returned after a failed  match  if  the  final  path
+       through  the  pattern involves (*MARK). However, unless (*MARK) used in
+       conjunction with (*COMMIT), this is unlikely to  happen  for  an  unan-
+       chored pattern because, as the starting point for matching is advanced,
+       the final check is often with an empty string, causing a failure before
+       (*MARK) is reached. For example:
+
+         /X(*MARK:A)Y|X(*MARK:B)Z/K
+         XP
+         No match
+
+       There are three potential starting points for this match (starting with
+       X, starting with P, and with  an  empty  string).  If  the  pattern  is
+       anchored, the result is different:
+
+         /^X(*MARK:A)Y|^X(*MARK:B)Z/K
+         XP
+         No match, mark = B
+
+       PCRE's  start-of-match  optimizations can also interfere with this. For
+       example, if, as a result of a call to pcre_study(), it knows the  mini-
+       mum  subject  length for a match, a shorter subject will not be scanned
+       at all.
+
+       Note that similar anomalies (though different in detail) exist in Perl,
+       no  doubt  for the same reasons. The use of (*MARK) data after a failed
+       match of an unanchored pattern is not recommended, unless (*COMMIT)  is
+       involved.
+
    Verbs that act after backtracking
 
        The following verbs do nothing when they are encountered. Matching con-
-       tinues  with what follows, but if there is no subsequent match, a fail-
-       ure is forced.  The verbs  differ  in  exactly  what  kind  of  failure
-       occurs.
+       tinues with what follows, but if there is no subsequent match,  causing
+       a  backtrack  to  the  verb, a failure is forced. That is, backtracking
+       cannot pass to the left of the verb. However, when one of  these  verbs
+       appears  inside  an atomic group, its effect is confined to that group,
+       because once the group has been matched, there is never any  backtrack-
+       ing  into  it.  In  this situation, backtracking can "jump back" to the
+       left of the entire atomic group. (Remember also, as stated above,  that
+       this localization also applies in subroutine calls and assertions.)
+
+       These  verbs  differ  in exactly what kind of failure occurs when back-
+       tracking reaches them.
 
          (*COMMIT)
 
-       This  verb  causes  the whole match to fail outright if the rest of the
-       pattern does not match. Even if the pattern is unanchored,  no  further
-       attempts  to  find  a match by advancing the starting point take place.
-       Once (*COMMIT) has been passed, pcre_exec() is committed to  finding  a
-       match at the current starting point, or not at all. For example:
+       This verb, which may not be followed by a name, causes the whole  match
+       to fail outright if the rest of the pattern does not match. Even if the
+       pattern is unanchored, no further attempts to find a match by advancing
+       the  starting  point  take  place.  Once  (*COMMIT)  has  been  passed,
+       pcre_exec() is committed to finding a match  at  the  current  starting
+       point, or not at all. For example:
 
          a+(*COMMIT)b
 
        This  matches  "xxaab" but not "aacaab". It can be thought of as a kind
-       of dynamic anchor, or "I've started, so I must finish."
-
-         (*PRUNE)
+       of dynamic anchor, or "I've started, so I must finish." The name of the
+       most  recently passed (*MARK) in the path is passed back when (*COMMIT)
+       forces a match failure.
+
+       Note that (*COMMIT) at the start of a pattern is not  the  same  as  an
+       anchor,  unless  PCRE's start-of-match optimizations are turned off, as
+       shown in this pcretest example:
+
+         /(*COMMIT)abc/
+         xyzabc
+          0: abc
+         xyzabc\Y
+         No match
 
-       This verb causes the match to fail at the current position if the  rest
-       of the pattern does not match. If the pattern is unanchored, the normal
-       "bumpalong" advance to the next starting character then happens.  Back-
-       tracking  can  occur as usual to the left of (*PRUNE), or when matching
-       to the right of (*PRUNE), but if there is no match to the right,  back-
-       tracking  cannot  cross (*PRUNE).  In simple cases, the use of (*PRUNE)
-       is just an alternative to an atomic group or possessive quantifier, but
-       there  are  some uses of (*PRUNE) that cannot be expressed in any other
-       way.
+       PCRE knows that any match must start  with  "a",  so  the  optimization
+       skips  along the subject to "a" before running the first match attempt,
+       which succeeds. When the optimization is disabled by the \Y  escape  in
+       the second subject, the match starts at "x" and so the (*COMMIT) causes
+       it to fail without trying any other starting points.
+
+         (*PRUNE) or (*PRUNE:NAME)
+
+       This verb causes the match to fail at the current starting position  in
+       the  subject  if the rest of the pattern does not match. If the pattern
+       is unanchored, the normal "bumpalong"  advance  to  the  next  starting
+       character  then happens. Backtracking can occur as usual to the left of
+       (*PRUNE), before it is reached,  or  when  matching  to  the  right  of
+       (*PRUNE),  but  if  there is no match to the right, backtracking cannot
+       cross (*PRUNE). In simple cases, the use of (*PRUNE) is just an  alter-
+       native  to an atomic group or possessive quantifier, but there are some
+       uses of (*PRUNE) that cannot be expressed in any other way.  The behav-
+       iour  of  (*PRUNE:NAME)  is  the  same as (*MARK:NAME)(*PRUNE) when the
+       match fails completely; the name is passed back if this  is  the  final
+       attempt.   (*PRUNE:NAME)  does  not  pass back a name if the match suc-
+       ceeds. In an anchored pattern (*PRUNE) has the same  effect  as  (*COM-
+       MIT).
 
          (*SKIP)
 
-       This verb is like (*PRUNE), except that if the pattern  is  unanchored,
-       the  "bumpalong" advance is not to the next character, but to the posi-
-       tion in the subject where (*SKIP) was  encountered.  (*SKIP)  signifies
-       that  whatever  text  was  matched leading up to it cannot be part of a
-       successful match. Consider:
+       This  verb, when given without a name, is like (*PRUNE), except that if
+       the pattern is unanchored, the "bumpalong" advance is not to  the  next
+       character, but to the position in the subject where (*SKIP) was encoun-
+       tered. (*SKIP) signifies that whatever text was matched leading  up  to
+       it cannot be part of a successful match. Consider:
 
          a+(*SKIP)b
 
-       If the subject is "aaaac...",  after  the  first  match  attempt  fails
-       (starting  at  the  first  character in the string), the starting point
+       If  the  subject  is  "aaaac...",  after  the first match attempt fails
+       (starting at the first character in the  string),  the  starting  point
        skips on to start the next attempt at "c". Note that a possessive quan-
-       tifer  does not have the same effect as this example; although it would
-       suppress backtracking  during  the  first  match  attempt,  the  second
-       attempt  would  start at the second character instead of skipping on to
+       tifer does not have the same effect as this example; although it  would
+       suppress  backtracking  during  the  first  match  attempt,  the second
+       attempt would start at the second character instead of skipping  on  to
        "c".
 
-         (*THEN)
+         (*SKIP:NAME)
+
+       When  (*SKIP) has an associated name, its behaviour is modified. If the
+       following pattern fails to match, the previous path through the pattern
+       is  searched for the most recent (*MARK) that has the same name. If one
+       is found, the "bumpalong" advance is to the subject position that  cor-
+       responds  to  that (*MARK) instead of to where (*SKIP) was encountered.
+       If no (*MARK) with a matching name is found, normal "bumpalong" of  one
+       character happens (the (*SKIP) is ignored).
+
+         (*THEN) or (*THEN:NAME)
 
        This verb causes a skip to the next alternation if the rest of the pat-
        tern does not match. That is, it cancels pending backtracking, but only
-       within the current alternation. Its name  comes  from  the  observation
+       within  the  current  alternation.  Its name comes from the observation
        that it can be used for a pattern-based if-then-else block:
 
          ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...
 
-       If  the COND1 pattern matches, FOO is tried (and possibly further items
-       after the end of the group if FOO succeeds);  on  failure  the  matcher
-       skips  to  the second alternative and tries COND2, without backtracking
-       into COND1. If (*THEN) is used outside  of  any  alternation,  it  acts
-       exactly like (*PRUNE).
+       If the COND1 pattern matches, FOO is tried (and possibly further  items
+       after  the  end  of  the group if FOO succeeds); on failure the matcher
+       skips to the second alternative and tries COND2,  without  backtracking
+       into  COND1.  The  behaviour  of  (*THEN:NAME)  is  exactly the same as
+       (*MARK:NAME)(*THEN) if the overall  match  fails.  If  (*THEN)  is  not
+       directly inside an alternation, it acts like (*PRUNE).
 
 
 SEE ALSO
@@ -5260,7 +5540,7 @@ AUTHOR
 
 REVISION
 
-       Last updated: 06 March 2010
+       Last updated: 18 May 2010
        Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
@@ -5308,6 +5588,7 @@ CHARACTER TYPES
          \D         a character that is not a decimal digit
          \h         a horizontal whitespace character
          \H         a character that is not a horizontal whitespace character
+         \N         a character that is not a newline
          \p{xx}     a character with the xx property
          \P{xx}     a character without the xx property
          \R         a newline sequence
@@ -5319,10 +5600,12 @@ CHARACTER TYPES
          \W         a "non-word" character
          \X         an extended Unicode sequence
 
-       In PCRE, \d, \D, \s, \S, \w, and \W recognize only ASCII characters.
+       In  PCRE,  by  default, \d, \D, \s, \S, \w, and \W recognize only ASCII
+       characters, even in UTF-8 mode. However, this can be changed by setting
+       the PCRE_UCP option.
 
 
-GENERAL CATEGORY PROPERTY CODES FOR \p and \P
+GENERAL CATEGORY PROPERTIES FOR \p and \P
 
          C          Other
          Cc         Control
@@ -5370,6 +5653,14 @@ GENERAL CATEGORY PROPERTY CODES FOR \p and \P
          Zs         Space separator
 
 
+PCRE SPECIAL CATEGORY PROPERTIES FOR \p and \P
+
+         Xan        Alphanumeric: union of properties L and N
+         Xps        POSIX space: property Z or tab, NL, VT, FF, CR
+         Xsp        Perl space: property Z or tab, NL, FF, CR
+         Xwd        Perl word: property Xan or underscore
+
+
 SCRIPT NAMES FOR \p AND \P
 
        Arabic, Armenian, Avestan, Balinese, Bamum, Bengali, Bopomofo, Braille,
@@ -5411,8 +5702,9 @@ CHARACTER CLASSES
          word        same as \w
          xdigit      hexadecimal digit
 
-       In PCRE, POSIX character set names recognize only ASCII characters. You
-       can use \Q...\E inside a character class.
+       In PCRE, POSIX character set names recognize only ASCII  characters  by
+       default,  but  some  of them use Unicode properties if PCRE_UCP is set.
+       You can use \Q...\E inside a character class.
 
 
 QUANTIFIERS
@@ -5437,7 +5729,7 @@ QUANTIFIERS
 
 ANCHORS AND SIMPLE ASSERTIONS
 
-         \b          word boundary (only ASCII letters recognized)
+         \b          word boundary
          \B          not a word boundary
          ^           start of subject
                       also after internal newline in multiline mode
@@ -5492,10 +5784,11 @@ OPTION SETTING
          (?x)            extended (ignore white space)
          (?-...)         unset option(s)
 
-       The following is recognized only at the start of a pattern or after one
-       of the newline-setting options with similar syntax:
+       The following are recognized only at the start of a  pattern  or  after
+       one of the newline-setting options with similar syntax:
 
-         (*UTF8)         set UTF-8 mode
+         (*UTF8)         set UTF-8 mode (PCRE_UTF8)
+         (*UCP)          set PCRE_UCP (use Unicode properties for \d etc)
 
 
 LOOKAHEAD AND LOOKBEHIND ASSERTIONS
@@ -5564,7 +5857,7 @@ BACKTRACKING CONTROL
          (*ACCEPT)       force successful match
          (*FAIL)         force backtrack; synonym (*F)
 
-       The following act only when a subsequent match failure causes  a  back-
+       The  following  act only when a subsequent match failure causes a back-
        track to reach them. They all force a match failure, but they differ in
        what happens afterwards. Those that advance the start-of-match point do
        so only if the pattern is not anchored.
@@ -5577,8 +5870,8 @@ BACKTRACKING CONTROL
 
 NEWLINE CONVENTIONS
 
-       These  are  recognized only at the very start of the pattern or after a
-       (*BSR_...) or (*UTF8) option.
+       These are recognized only at the very start of the pattern or  after  a
+       (*BSR_...) or (*UTF8) or (*UCP) option.
 
          (*CR)           carriage return only
          (*LF)           linefeed only
@@ -5589,8 +5882,8 @@ NEWLINE CONVENTIONS
 
 WHAT \R MATCHES
 
-       These are recognized only at the very start of the pattern or  after  a
-       (*...) option that sets the newline convention or UTF-8 mode.
+       These  are  recognized only at the very start of the pattern or after a
+       (*...) option that sets the newline convention or UTF-8 or UCP mode.
 
          (*BSR_ANYCRLF)  CR, LF, or CRLF
          (*BSR_UNICODE)  any Unicode newline sequence
@@ -5616,7 +5909,7 @@ AUTHOR
 
 REVISION
 
-       Last updated: 01 March 2010
+       Last updated: 12 May 2010
        Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
@@ -6217,6 +6510,14 @@ PROCESSING TIME
        If you can find an alternative pattern  that  does  not  use  character
        properties, it will probably be faster.
 
+       By  default,  the  escape  sequences  \b, \d, \s, and \w, and the POSIX
+       character classes such as [:alpha:]  do  not  use  Unicode  properties,
+       partly for backwards compatibility, and partly for performance reasons.
+       However, you can set PCRE_UCP if you want Unicode character  properties
+       to  be  used.  This  can double the matching time for items such as \d,
+       when matched with  pcre_exec();  the  performance  loss  is  less  with
+       pcre_dfa_exec(), and in both cases there is not much difference for \b.
+
        When  a  pattern  begins  with .* not in parentheses, or in parentheses
        that are not the subject of a backreference, and the PCRE_DOTALL option
        is  set, the pattern is implicitly anchored by PCRE, since it can match
@@ -6282,7 +6583,7 @@ AUTHOR
 
 REVISION
 
-       Last updated: 07 March 2010
+       Last updated: 16 May 2010
        Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
@@ -6388,33 +6689,40 @@ COMPILING A PATTERN
        ing,  the  nmatch  and  pmatch  arguments  are ignored, and no captured
        strings are returned.
 
+         REG_UCP
+
+       The PCRE_UCP option is set when the regular expression  is  passed  for
+       compilation  to  the  native  function. This causes PCRE to use Unicode
+       properties when matchine \d, \w,  etc.,  instead  of  just  recognizing
+       ASCII values. Note that REG_UTF8 is not part of the POSIX standard.
+
          REG_UNGREEDY
 
-       The PCRE_UNGREEDY option is set when the regular expression  is  passed
-       for  compilation  to the native function. Note that REG_UNGREEDY is not
+       The  PCRE_UNGREEDY  option is set when the regular expression is passed
+       for compilation to the native function. Note that REG_UNGREEDY  is  not
        part of the POSIX standard.
 
          REG_UTF8
 
-       The PCRE_UTF8 option is set when the regular expression is  passed  for
-       compilation  to the native function. This causes the pattern itself and
-       all data strings used for matching it to be treated as  UTF-8  strings.
+       The  PCRE_UTF8  option is set when the regular expression is passed for
+       compilation to the native function. This causes the pattern itself  and
+       all  data  strings used for matching it to be treated as UTF-8 strings.
        Note that REG_UTF8 is not part of the POSIX standard.
 
-       In  the  absence  of  these  flags, no options are passed to the native
-       function.  This means the the  regex  is  compiled  with  PCRE  default
-       semantics.  In particular, the way it handles newline characters in the
-       subject string is the Perl way, not the POSIX way.  Note  that  setting
-       PCRE_MULTILINE  has only some of the effects specified for REG_NEWLINE.
-       It does not affect the way newlines are matched by . (they are not)  or
+       In the absence of these flags, no options  are  passed  to  the  native
+       function.   This  means  the  the  regex  is compiled with PCRE default
+       semantics. In particular, the way it handles newline characters in  the
+       subject  string  is  the Perl way, not the POSIX way. Note that setting
+       PCRE_MULTILINE has only some of the effects specified for  REG_NEWLINE.
+       It  does not affect the way newlines are matched by . (they are not) or
        by a negative class such as [^a] (they are).
 
-       The  yield of regcomp() is zero on success, and non-zero otherwise. The
+       The yield of regcomp() is zero on success, and non-zero otherwise.  The
        preg structure is filled in on success, and one member of the structure
-       is  public: re_nsub contains the number of capturing subpatterns in the
+       is public: re_nsub contains the number of capturing subpatterns in  the
        regular expression. Various error codes are defined in the header file.
 
-       NOTE: If the yield of regcomp() is non-zero, you must  not  attempt  to
+       NOTE:  If  the  yield of regcomp() is non-zero, you must not attempt to
        use the contents of the preg structure. If, for example, you pass it to
        regexec(), the result is undefined and your program is likely to crash.
 
@@ -6422,9 +6730,9 @@ COMPILING A PATTERN
 MATCHING NEWLINE CHARACTERS
 
        This area is not simple, because POSIX and Perl take different views of
-       things.   It  is  not possible to get PCRE to obey POSIX semantics, but
-       then PCRE was never intended to be a POSIX engine. The following  table
-       lists  the  different  possibilities for matching newline characters in
+       things.  It is not possible to get PCRE to obey  POSIX  semantics,  but
+       then  PCRE was never intended to be a POSIX engine. The following table
+       lists the different possibilities for matching  newline  characters  in
        PCRE:
 
                                  Default   Change with
@@ -6446,19 +6754,19 @@ MATCHING NEWLINE CHARACTERS
          ^ matches \n in middle     no     REG_NEWLINE
 
        PCRE's behaviour is the same as Perl's, except that there is no equiva-
-       lent  for  PCRE_DOLLAR_ENDONLY in Perl. In both PCRE and Perl, there is
+       lent for PCRE_DOLLAR_ENDONLY in Perl. In both PCRE and Perl,  there  is
        no way to stop newline from matching [^a].
 
-       The  default  POSIX  newline  handling  can  be  obtained  by   setting
-       PCRE_DOTALL  and  PCRE_DOLLAR_ENDONLY, but there is no way to make PCRE
+       The   default  POSIX  newline  handling  can  be  obtained  by  setting
+       PCRE_DOTALL and PCRE_DOLLAR_ENDONLY, but there is no way to  make  PCRE
        behave exactly as for the REG_NEWLINE action.
 
 
 MATCHING A PATTERN
 
-       The function regexec() is called  to  match  a  compiled  pattern  preg
-       against  a  given string, which is by default terminated by a zero byte
-       (but see REG_STARTEND below), subject to the options in  eflags.  These
+       The  function  regexec()  is  called  to  match a compiled pattern preg
+       against a given string, which is by default terminated by a  zero  byte
+       (but  see  REG_STARTEND below), subject to the options in eflags. These
        can be:
 
          REG_NOTBOL
@@ -6480,17 +6788,17 @@ MATCHING A PATTERN
 
          REG_STARTEND
 
-       The string is considered to start at string +  pmatch[0].rm_so  and  to
-       have  a terminating NUL located at string + pmatch[0].rm_eo (there need
-       not actually be a NUL at that location), regardless  of  the  value  of
-       nmatch.  This  is a BSD extension, compatible with but not specified by
-       IEEE Standard 1003.2 (POSIX.2), and should  be  used  with  caution  in
+       The  string  is  considered to start at string + pmatch[0].rm_so and to
+       have a terminating NUL located at string + pmatch[0].rm_eo (there  need
+       not  actually  be  a  NUL at that location), regardless of the value of
+       nmatch. This is a BSD extension, compatible with but not  specified  by
+       IEEE  Standard  1003.2  (POSIX.2),  and  should be used with caution in
        software intended to be portable to other systems. Note that a non-zero
        rm_so does not imply REG_NOTBOL; REG_STARTEND affects only the location
        of the string, not how it is matched.
 
-       If  the pattern was compiled with the REG_NOSUB flag, no data about any
-       matched strings  is  returned.  The  nmatch  and  pmatch  arguments  of
+       If the pattern was compiled with the REG_NOSUB flag, no data about  any
+       matched  strings  is  returned.  The  nmatch  and  pmatch  arguments of
        regexec() are ignored.
 
        If the value of nmatch is zero, or if the value pmatch is NULL, no data
@@ -6498,34 +6806,34 @@ MATCHING A PATTERN
 
        Otherwise,the portion of the string that was matched, and also any cap-
        tured substrings, are returned via the pmatch argument, which points to
-       an array of nmatch structures of type regmatch_t, containing  the  mem-
-       bers  rm_so  and rm_eo. These contain the offset to the first character
-       of each substring and the offset to the first character after  the  end
-       of  each substring, respectively. The 0th element of the vector relates
-       to the entire portion of string that was matched;  subsequent  elements
-       relate  to  the capturing subpatterns of the regular expression. Unused
+       an  array  of nmatch structures of type regmatch_t, containing the mem-
+       bers rm_so and rm_eo. These contain the offset to the  first  character
+       of  each  substring and the offset to the first character after the end
+       of each substring, respectively. The 0th element of the vector  relates
+       to  the  entire portion of string that was matched; subsequent elements
+       relate to the capturing subpatterns of the regular  expression.  Unused
        entries in the array have both structure members set to -1.
 
-       A successful match yields  a  zero  return;  various  error  codes  are
-       defined  in  the  header  file,  of which REG_NOMATCH is the "expected"
+       A  successful  match  yields  a  zero  return;  various error codes are
+       defined in the header file, of  which  REG_NOMATCH  is  the  "expected"
        failure code.
 
 
 ERROR MESSAGES
 
        The regerror() function maps a non-zero errorcode from either regcomp()
-       or  regexec()  to  a  printable message. If preg is not NULL, the error
+       or regexec() to a printable message. If preg is  not  NULL,  the  error
        should have arisen from the use of that structure. A message terminated
-       by  a  binary  zero  is  placed  in  errbuf. The length of the message,
-       including the zero, is limited to errbuf_size. The yield of  the  func-
+       by a binary zero is placed  in  errbuf.  The  length  of  the  message,
+       including  the  zero, is limited to errbuf_size. The yield of the func-
        tion is the size of buffer needed to hold the whole message.
 
 
 MEMORY USAGE
 
-       Compiling  a regular expression causes memory to be allocated and asso-
-       ciated with the preg structure. The function regfree() frees  all  such
-       memory,  after  which  preg may no longer be used as a compiled expres-
+       Compiling a regular expression causes memory to be allocated and  asso-
+       ciated  with  the preg structure. The function regfree() frees all such
+       memory, after which preg may no longer be used as  a  compiled  expres-
        sion.
 
 
@@ -6538,8 +6846,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 02 September 2009
-       Copyright (c) 1997-2009 University of Cambridge.
+       Last updated: 16 May 2010
+       Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 
 
@@ -6925,8 +7233,14 @@ PCRE SAMPLE PROGRAM
          gcc -o pcredemo -I/usr/local/include pcredemo.c \
              -L/usr/local/lib -lpcre
 
-       Once you have compiled the demonstration program, you  can  run  simple
-       tests like this:
+       In a Windows environment, if you want to statically  link  the  program
+       against a non-dll pcre.a file, you must uncomment the line that defines
+       PCRE_STATIC before including pcre.h, because  otherwise  the  pcre_mal-
+       loc()   and   pcre_free()   exported   functions   will   be   declared
+       __declspec(dllimport), with unwanted results.
+
+       Once you have compiled and linked the demonstration  program,  you  can
+       run simple tests like this:
 
          ./pcredemo 'cat|dog' 'the cat sat on the mat'
          ./pcredemo -g 'cat|dog' 'the dog sat on the cat'
@@ -6960,8 +7274,8 @@ AUTHOR
 
 REVISION
 
-       Last updated: 30 September 2009
-       Copyright (c) 1997-2009 University of Cambridge.
+       Last updated: 26 May 2010
+       Copyright (c) 1997-2010 University of Cambridge.
 ------------------------------------------------------------------------------
 PCRESTACK(3)                                                      PCRESTACK(3)
 
index 890b13de657e4dd25a60d2b793de34da44d8a7cd..febb617422a6ca33e9491b5278343653a3e6471c 100644 (file)
@@ -5,7 +5,7 @@
 /* This is the public header file for the PCRE library, to be #included by
 applications that call the PCRE functions.
 
-           Copyright (c) 1997-2009 University of Cambridge
+           Copyright (c) 1997-2010 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
 /* The current PCRE version information. */
 
 #define PCRE_MAJOR          8
-#define PCRE_MINOR          02
+#define PCRE_MINOR          10
 #define PCRE_PRERELEASE     
-#define PCRE_DATE           2010-03-19
+#define PCRE_DATE           2010-06-25
 
 /* When an application links to a PCRE DLL in Windows, the symbols that are
 imported have to be identified as such. When building PCRE, the appropriate
@@ -131,6 +131,7 @@ both, so we keep them all distinct. */
 #define PCRE_NO_START_OPTIMISE  0x04000000
 #define PCRE_PARTIAL_HARD       0x08000000
 #define PCRE_NOTEMPTY_ATSTART   0x10000000
+#define PCRE_UCP                0x20000000
 
 /* Exec-time and get/set-time error codes */
 
@@ -200,6 +201,7 @@ these bits, just add new ones on the end, in order to remain compatible. */
 #define PCRE_EXTRA_CALLOUT_DATA           0x0004
 #define PCRE_EXTRA_TABLES                 0x0008
 #define PCRE_EXTRA_MATCH_LIMIT_RECURSION  0x0010
+#define PCRE_EXTRA_MARK                   0x0020
 
 /* Types */
 
@@ -225,6 +227,7 @@ typedef struct pcre_extra {
   void *callout_data;             /* Data passed back in callouts */
   const unsigned char *tables;    /* Pointer to character tables */
   unsigned long int match_limit_recursion; /* Max recursive calls to match() */
+  unsigned char **mark;           /* For passing back a mark pointer */
 } pcre_extra;
 
 /* The structure for passing out data via the pcre_callout_function. We use a
index f1dbaaedf2978ceee61d0bbddf45e3022dc3fe0d..980c23f1cd78d78f20574f55dcb4223195113789 100644 (file)
@@ -14,7 +14,7 @@ example ISO-8859-1. When dftables is run, it creates these tables in the
 current locale. If PCRE is configured with --enable-rebuild-chartables, this
 happens automatically.
 
-The following #includes are present because without the gcc 4.x may remove the
+The following #includes are present because without them gcc 4.x may remove the
 array definition from the final binary if PCRE is built into a static library
 and dead code stripping is activated. This leads to link errors. Pulling in the
 header ensures that the array gets flagged as "someone outside this compilation
index 54e23ea39e2c32c2f806af32f690d8cb07d02740..53027e603d980b69641b0aea878d31a693d5adf1 100644 (file)
@@ -122,7 +122,7 @@ static const short int escapes[] = {
      -ESC_H,                  0,
      0,                       -ESC_K,
      0,                       0,
-     0,                       0,
+     -ESC_N,                  0,
      -ESC_P,                  -ESC_Q,
      -ESC_R,                  -ESC_S,
      0,                       0,
@@ -169,7 +169,7 @@ static const short int escapes[] = {
 /*  B8 */     0,     0,      0,       0,      0,   ']',    '=',    '-',
 /*  C0 */   '{',-ESC_A, -ESC_B,  -ESC_C, -ESC_D,-ESC_E,      0, -ESC_G,
 /*  C8 */-ESC_H,     0,      0,       0,      0,     0,      0,      0,
-/*  D0 */   '}',     0, -ESC_K,       0,      0,     0,      0, -ESC_P,
+/*  D0 */   '}',     0, -ESC_K,       0,      0,-ESC_N,      0, -ESC_P,
 /*  D8 */-ESC_Q,-ESC_R,      0,       0,      0,     0,      0,      0,
 /*  E0 */  '\\',     0, -ESC_S,       0,      0,-ESC_V, -ESC_W, -ESC_X,
 /*  E8 */     0,-ESC_Z,      0,       0,      0,     0,      0,      0,
@@ -186,11 +186,14 @@ string is built from string macros so that it works in UTF-8 mode on EBCDIC
 platforms. */
 
 typedef struct verbitem {
-  int   len;
-  int   op;
+  int   len;                 /* Length of verb name */
+  int   op;                  /* Op when no arg, or -1 if arg mandatory */
+  int   op_arg;              /* Op when arg present, or -1 if not allowed */
 } verbitem;
 
 static const char verbnames[] =
+  "\0"                       /* Empty name is a shorthand for MARK */
+  STRING_MARK0
   STRING_ACCEPT0
   STRING_COMMIT0
   STRING_F0
@@ -200,13 +203,15 @@ static const char verbnames[] =
   STRING_THEN;
 
 static const verbitem verbs[] = {
-  { 6, OP_ACCEPT },
-  { 6, OP_COMMIT },
-  { 1, OP_FAIL },
-  { 4, OP_FAIL },
-  { 5, OP_PRUNE },
-  { 4, OP_SKIP  },
-  { 4, OP_THEN  }
+  { 0, -1,        OP_MARK },
+  { 4, -1,        OP_MARK },
+  { 6, OP_ACCEPT, -1 },
+  { 6, OP_COMMIT, -1 },
+  { 1, OP_FAIL,   -1 },
+  { 4, OP_FAIL,   -1 },
+  { 5, OP_PRUNE,  OP_PRUNE_ARG },
+  { 4, OP_SKIP,   OP_SKIP_ARG  },
+  { 4, OP_THEN,   OP_THEN_ARG  }
 };
 
 static const int verbcount = sizeof(verbs)/sizeof(verbitem);
@@ -254,6 +259,53 @@ static const int posix_class_maps[] = {
   cbit_xdigit,-1,          0              /* xdigit */
 };
 
+/* Table of substitutes for \d etc when PCRE_UCP is set. The POSIX class
+substitutes must be in the order of the names, defined above, and there are
+both positive and negative cases. NULL means no substitute. */
+
+#ifdef SUPPORT_UCP
+static const uschar *substitutes[] = {
+  (uschar *)"\\P{Nd}",    /* \D */
+  (uschar *)"\\p{Nd}",    /* \d */
+  (uschar *)"\\P{Xsp}",   /* \S */       /* NOTE: Xsp is Perl space */
+  (uschar *)"\\p{Xsp}",   /* \s */
+  (uschar *)"\\P{Xwd}",   /* \W */
+  (uschar *)"\\p{Xwd}"    /* \w */
+};
+
+static const uschar *posix_substitutes[] = {
+  (uschar *)"\\p{L}",     /* alpha */
+  (uschar *)"\\p{Ll}",    /* lower */
+  (uschar *)"\\p{Lu}",    /* upper */
+  (uschar *)"\\p{Xan}",   /* alnum */
+  NULL,                   /* ascii */
+  (uschar *)"\\h",        /* blank */
+  NULL,                   /* cntrl */
+  (uschar *)"\\p{Nd}",    /* digit */
+  NULL,                   /* graph */
+  NULL,                   /* print */
+  NULL,                   /* punct */
+  (uschar *)"\\p{Xps}",   /* space */    /* NOTE: Xps is POSIX space */
+  (uschar *)"\\p{Xwd}",   /* word */
+  NULL,                   /* xdigit */
+  /* Negated cases */
+  (uschar *)"\\P{L}",     /* ^alpha */
+  (uschar *)"\\P{Ll}",    /* ^lower */
+  (uschar *)"\\P{Lu}",    /* ^upper */
+  (uschar *)"\\P{Xan}",   /* ^alnum */
+  NULL,                   /* ^ascii */
+  (uschar *)"\\H",        /* ^blank */
+  NULL,                   /* ^cntrl */
+  (uschar *)"\\P{Nd}",    /* ^digit */
+  NULL,                   /* ^graph */
+  NULL,                   /* ^print */
+  NULL,                   /* ^punct */
+  (uschar *)"\\P{Xps}",   /* ^space */   /* NOTE: Xps is POSIX space */
+  (uschar *)"\\P{Xwd}",   /* ^word */
+  NULL                    /* ^xdigit */
+};
+#define POSIX_SUBSIZE (sizeof(posix_substitutes)/sizeof(uschar *))
+#endif
 
 #define STRING(a)  # a
 #define XSTRING(s) STRING(s)
@@ -317,7 +369,7 @@ static const char error_texts[] =
   /* 35 */
   "invalid condition (?(0)\0"
   "\\C not allowed in lookbehind assertion\0"
-  "PCRE does not support \\L, \\l, \\N, \\U, or \\u\0"
+  "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0"
   "number after (?C is > 255\0"
   "closing ) for (?C expected\0"
   /* 40 */
@@ -343,7 +395,7 @@ static const char error_texts[] =
   "inconsistent NEWLINE options\0"
   "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"
   "a numbered reference must not be zero\0"
-  "(*VERB) with an argument is not supported\0"
+  "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0"
   /* 60 */
   "(*VERB) not recognized\0"
   "number is too big\0"
@@ -351,7 +403,10 @@ static const char error_texts[] =
   "digit expected after (?+\0"
   "] is an invalid data character in JavaScript compatibility mode\0"
   /* 65 */
-  "different names for subpatterns of the same number are not allowed\0";
+  "different names for subpatterns of the same number are not allowed\0"
+  "(*MARK) must have an argument\0"
+  "this version of PCRE is not compiled with PCRE_UCP support\0"
+  ;
 
 /* Table to identify digits and hex digits. This is used when compiling
 patterns. Note that the tables in chartables are dependent on the locale, and
@@ -584,7 +639,6 @@ else
 
     case CHAR_l:
     case CHAR_L:
-    case CHAR_N:
     case CHAR_u:
     case CHAR_U:
     *errorcodeptr = ERR37;
@@ -822,6 +876,19 @@ else
     }
   }
 
+/* Perl supports \N{name} for character names, as well as plain \N for "not
+newline". PCRE does not support \N{name}. */
+
+if (c == -ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+  *errorcodeptr = ERR37;
+
+/* If PCRE_UCP is set, we change the values for \d etc. */
+
+if ((options & PCRE_UCP) != 0 && c <= -ESC_D && c >= -ESC_w)
+  c -= (ESC_DU - ESC_D);
+
+/* Set the pointer to the final character before returning. */
+
 *ptrptr = ptr;
 return c;
 }
@@ -1060,25 +1127,39 @@ dealing with. The very first call may not start with a parenthesis. */
 
 if (ptr[0] == CHAR_LEFT_PARENTHESIS)
   {
-  if (ptr[1] == CHAR_QUESTION_MARK &&
-      ptr[2] == CHAR_VERTICAL_LINE)
+  /* Handle specials such as (*SKIP) or (*UTF8) etc. */
+
+  if (ptr[1] == CHAR_ASTERISK) ptr += 2;
+
+  /* Handle a normal, unnamed capturing parenthesis. */
+
+  else if (ptr[1] != CHAR_QUESTION_MARK)
+    {
+    *count += 1;
+    if (name == NULL && *count == lorn) return *count;
+    ptr++;
+    }
+
+  /* All cases now have (? at the start. Remember when we are in a group
+  where the parenthesis numbers are duplicated. */
+
+  else if (ptr[2] == CHAR_VERTICAL_LINE)
     {
     ptr += 3;
     dup_parens = TRUE;
     }
 
-  /* Handle a normal, unnamed capturing parenthesis */
+  /* Handle comments; all characters are allowed until a ket is reached. */
 
-  else if (ptr[1] != CHAR_QUESTION_MARK && ptr[1] != CHAR_ASTERISK)
+  else if (ptr[2] == CHAR_NUMBER_SIGN)
     {
-    *count += 1;
-    if (name == NULL && *count == lorn) return *count;
-    ptr++;
+    for (ptr += 3; *ptr != 0; ptr++) if (*ptr == CHAR_RIGHT_PARENTHESIS) break;
+    goto FAIL_EXIT;
     }
 
   /* Handle a condition. If it is an assertion, just carry on so that it
   is processed as normal. If not, skip to the closing parenthesis of the
-  condition (there can't be any nested parens. */
+  condition (there can't be any nested parens). */
 
   else if (ptr[2] == CHAR_LEFT_PARENTHESIS)
     {
@@ -1090,7 +1171,7 @@ if (ptr[0] == CHAR_LEFT_PARENTHESIS)
       }
     }
 
-  /* We have either (? or (* and not a condition */
+  /* Start with (? but not a condition. */
 
   else
     {
@@ -1212,8 +1293,7 @@ for (; *ptr != 0; ptr++)
   else if (*ptr == CHAR_RIGHT_PARENTHESIS)
     {
     if (dup_parens && *count < hwm_count) *count = hwm_count;
-    *ptrptr = ptr;
-    return -1;
+    goto FAIL_EXIT;
     }
 
   else if (*ptr == CHAR_VERTICAL_LINE && dup_parens)
@@ -1613,7 +1693,8 @@ for (;;)
 
   /* 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. */
+  two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
+  must add in its length. */
 
   else
     {
@@ -1637,6 +1718,13 @@ for (;;)
       case OP_TYPEPOSUPTO:
       if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
       break;
+
+      case OP_MARK:
+      case OP_PRUNE_ARG:
+      case OP_SKIP_ARG:
+      case OP_THEN_ARG:
+      code += code[1];
+      break;
       }
 
     /* Add in the fixed length from the table */
@@ -1708,7 +1796,8 @@ for (;;)
 
   /* 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. */
+  two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
+  must add in its length. */
 
   else
     {
@@ -1732,6 +1821,13 @@ for (;;)
       case OP_TYPEEXACT:
       if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
       break;
+
+      case OP_MARK:
+      case OP_PRUNE_ARG:
+      case OP_SKIP_ARG:
+      case OP_THEN_ARG:
+      code += code[1];
+      break;
       }
 
     /* Add in the fixed length from the table */
@@ -2001,6 +2097,16 @@ for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE
     break;
 #endif
 
+    /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument
+    string. */
+
+    case OP_MARK:
+    case OP_PRUNE_ARG:
+    case OP_SKIP_ARG:
+    case OP_THEN_ARG:
+    code += code[1];
+    break;
+
     /* None of the remaining opcodes are required to match a character. */
 
     default:
@@ -2221,8 +2327,8 @@ auto_callout(uschar *code, const uschar *ptr, compile_data *cd)
 {
 *code++ = OP_CALLOUT;
 *code++ = 255;
-PUT(code, 0, ptr - cd->start_pattern);  /* Pattern offset */
-PUT(code, LINK_SIZE, 0);                /* Default length */
+PUT(code, 0, (int)(ptr - cd->start_pattern));  /* Pattern offset */
+PUT(code, LINK_SIZE, 0);                       /* Default length */
 return code + 2*LINK_SIZE;
 }
 
@@ -2247,7 +2353,7 @@ Returns:             nothing
 static void
 complete_callout(uschar *previous_callout, const uschar *ptr, compile_data *cd)
 {
-int length = ptr - cd->start_pattern - GET(previous_callout, 2);
+int length = (int)(ptr - cd->start_pattern - GET(previous_callout, 2));
 PUT(previous_callout, 2 + LINK_SIZE, length);
 }
 
@@ -2297,6 +2403,69 @@ for (++c; c <= d; c++)
 
 return TRUE;
 }
+
+
+
+/*************************************************
+*        Check a character and a property        *
+*************************************************/
+
+/* This function is called by check_auto_possessive() when a property item
+is adjacent to a fixed character.
+
+Arguments:
+  c            the character
+  ptype        the property type
+  pdata        the data for the type
+  negated      TRUE if it's a negated property (\P or \p{^)
+
+Returns:       TRUE if auto-possessifying is OK
+*/
+
+static BOOL
+check_char_prop(int c, int ptype, int pdata, BOOL negated)
+{
+const ucd_record *prop = GET_UCD(c);
+switch(ptype)
+  {
+  case PT_LAMP:
+  return (prop->chartype == ucp_Lu ||
+          prop->chartype == ucp_Ll ||
+          prop->chartype == ucp_Lt) == negated;
+
+  case PT_GC:
+  return (pdata == _pcre_ucp_gentype[prop->chartype]) == negated;
+
+  case PT_PC:
+  return (pdata == prop->chartype) == negated;
+
+  case PT_SC:
+  return (pdata == prop->script) == negated;
+
+  /* These are specials */
+
+  case PT_ALNUM:
+  return (_pcre_ucp_gentype[prop->chartype] == ucp_L ||
+          _pcre_ucp_gentype[prop->chartype] == ucp_N) == negated;
+
+  case PT_SPACE:    /* Perl space */
+  return (_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
+          c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
+          == negated;
+
+  case PT_PXSPACE:  /* POSIX space */
+  return (_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
+          c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+          c == CHAR_FF || c == CHAR_CR)
+          == negated;
+
+  case PT_WORD:
+  return (_pcre_ucp_gentype[prop->chartype] == ucp_L ||
+          _pcre_ucp_gentype[prop->chartype] == ucp_N ||
+          c == CHAR_UNDERSCORE) == negated;
+  }
+return FALSE;
+}
 #endif  /* SUPPORT_UCP */
 
 
@@ -2310,10 +2479,8 @@ whether the next thing could possibly match the repeated item. If not, it makes
 sense to automatically possessify the repeated item.
 
 Arguments:
-  op_code       the repeated op code
-  this          data for this item, depends on the opcode
+  previous      pointer to the repeated opcode
   utf8          TRUE in UTF-8 mode
-  utf8_char     used for utf8 character bytes, NULL if not relevant
   ptr           next character in pattern
   options       options bits
   cd            contains pointers to tables etc.
@@ -2322,10 +2489,11 @@ Returns:        TRUE if possessifying is wanted
 */
 
 static BOOL
-check_auto_possessive(int op_code, int item, BOOL utf8, uschar *utf8_char,
-  const uschar *ptr, int options, compile_data *cd)
+check_auto_possessive(const uschar *previous, BOOL utf8, const uschar *ptr,
+  int options, compile_data *cd)
 {
-int next;
+int c, next;
+int op_code = *previous++;
 
 /* Skip whitespace and comments in extended mode */
 
@@ -2386,23 +2554,18 @@ if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK ||
   strncmp((char *)ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0)
     return FALSE;
 
-/* Now compare the next item with the previous opcode. If the previous is a
-positive single character match, "item" either contains the character or, if
-"item" is greater than 127 in utf8 mode, the character's bytes are in
-utf8_char. */
-
-
-/* Handle cases when the next item is a character. */
+/* Now compare the next item with the previous opcode. First, handle cases when
+the next item is a character. */
 
 if (next >= 0) switch(op_code)
   {
   case OP_CHAR:
 #ifdef SUPPORT_UTF8
-  if (utf8 && item > 127) { GETCHAR(item, utf8_char); }
+  GETCHARTEST(c, previous);
 #else
-  (void)(utf8_char);  /* Keep compiler happy by referencing function argument */
+  c = *previous;
 #endif
-  return item != next;
+  return c != next;
 
   /* For CHARNC (caseless character) we must check the other case. If we have
   Unicode property support, we can use it to test the other case of
@@ -2410,9 +2573,11 @@ if (next >= 0) switch(op_code)
 
   case OP_CHARNC:
 #ifdef SUPPORT_UTF8
-  if (utf8 && item > 127) { GETCHAR(item, utf8_char); }
+  GETCHARTEST(c, previous);
+#else
+  c = *previous;
 #endif
-  if (item == next) return FALSE;
+  if (c == next) return FALSE;
 #ifdef SUPPORT_UTF8
   if (utf8)
     {
@@ -2423,16 +2588,16 @@ if (next >= 0) switch(op_code)
 #else
     othercase = NOTACHAR;
 #endif
-    return (unsigned int)item != othercase;
+    return (unsigned int)c != othercase;
     }
   else
 #endif  /* SUPPORT_UTF8 */
-  return (item != cd->fcc[next]);  /* Non-UTF-8 mode */
+  return (c != cd->fcc[next]);  /* Non-UTF-8 mode */
 
-  /* For OP_NOT, "item" must be a single-byte character. */
+  /* For OP_NOT, its data is always a single-byte character. */
 
   case OP_NOT:
-  if (item == next) return TRUE;
+  if ((c = *previous) == next) return TRUE;
   if ((options & PCRE_CASELESS) == 0) return FALSE;
 #ifdef SUPPORT_UTF8
   if (utf8)
@@ -2444,11 +2609,14 @@ if (next >= 0) switch(op_code)
 #else
     othercase = NOTACHAR;
 #endif
-    return (unsigned int)item == othercase;
+    return (unsigned int)c == othercase;
     }
   else
 #endif  /* SUPPORT_UTF8 */
-  return (item == cd->fcc[next]);  /* Non-UTF-8 mode */
+  return (c == cd->fcc[next]);  /* Non-UTF-8 mode */
+
+  /* Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not* set.
+  When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
 
   case OP_DIGIT:
   return next > 127 || (cd->ctypes[next] & ctype_digit) == 0;
@@ -2491,11 +2659,12 @@ if (next >= 0) switch(op_code)
     case 0x202f:
     case 0x205f:
     case 0x3000:
-    return op_code != OP_HSPACE;
+    return op_code == OP_NOT_HSPACE;
     default:
-    return op_code == OP_HSPACE;
+    return op_code != OP_NOT_HSPACE;
     }
 
+  case OP_ANYNL:
   case OP_VSPACE:
   case OP_NOT_VSPACE:
   switch(next)
@@ -2507,48 +2676,62 @@ if (next >= 0) switch(op_code)
     case 0x85:
     case 0x2028:
     case 0x2029:
-    return op_code != OP_VSPACE;
+    return op_code == OP_NOT_VSPACE;
     default:
-    return op_code == OP_VSPACE;
+    return op_code != OP_NOT_VSPACE;
     }
 
+#ifdef SUPPORT_UCP
+  case OP_PROP:
+  return check_char_prop(next, previous[0], previous[1], FALSE);
+
+  case OP_NOTPROP:
+  return check_char_prop(next, previous[0], previous[1], TRUE);
+#endif
+
   default:
   return FALSE;
   }
 
 
-/* Handle the case when the next item is \d, \s, etc. */
+/* Handle the case when the next item is \d, \s, etc. Note that when PCRE_UCP
+is set, \d turns into ESC_du rather than ESC_d, etc., so ESC_d etc. are
+generated only when PCRE_UCP is *not* set, that is, when only ASCII
+characteristics are recognized. Similarly, the opcodes OP_DIGIT etc. are
+replaced by OP_PROP codes when PCRE_UCP is set. */
 
 switch(op_code)
   {
   case OP_CHAR:
   case OP_CHARNC:
 #ifdef SUPPORT_UTF8
-  if (utf8 && item > 127) { GETCHAR(item, utf8_char); }
+  GETCHARTEST(c, previous);
+#else
+  c = *previous;
 #endif
   switch(-next)
     {
     case ESC_d:
-    return item > 127 || (cd->ctypes[item] & ctype_digit) == 0;
+    return c > 127 || (cd->ctypes[c] & ctype_digit) == 0;
 
     case ESC_D:
-    return item <= 127 && (cd->ctypes[item] & ctype_digit) != 0;
+    return c <= 127 && (cd->ctypes[c] & ctype_digit) != 0;
 
     case ESC_s:
-    return item > 127 || (cd->ctypes[item] & ctype_space) == 0;
+    return c > 127 || (cd->ctypes[c] & ctype_space) == 0;
 
     case ESC_S:
-    return item <= 127 && (cd->ctypes[item] & ctype_space) != 0;
+    return c <= 127 && (cd->ctypes[c] & ctype_space) != 0;
 
     case ESC_w:
-    return item > 127 || (cd->ctypes[item] & ctype_word) == 0;
+    return c > 127 || (cd->ctypes[c] & ctype_word) == 0;
 
     case ESC_W:
-    return item <= 127 && (cd->ctypes[item] & ctype_word) != 0;
+    return c <= 127 && (cd->ctypes[c] & ctype_word) != 0;
 
     case ESC_h:
     case ESC_H:
-    switch(item)
+    switch(c)
       {
       case 0x09:
       case 0x20:
@@ -2576,7 +2759,7 @@ switch(op_code)
 
     case ESC_v:
     case ESC_V:
-    switch(item)
+    switch(c)
       {
       case 0x0a:
       case 0x0b:
@@ -2590,38 +2773,92 @@ switch(op_code)
       return -next == ESC_v;
       }
 
+    /* When PCRE_UCP is set, these values get generated for \d etc. Find
+    their substitutions and process them. The result will always be either
+    -ESC_p or -ESC_P. Then fall through to process those values. */
+
+#ifdef SUPPORT_UCP
+    case ESC_du:
+    case ESC_DU:
+    case ESC_wu:
+    case ESC_WU:
+    case ESC_su:
+    case ESC_SU:
+      {
+      int temperrorcode = 0;
+      ptr = substitutes[-next - ESC_DU];
+      next = check_escape(&ptr, &temperrorcode, 0, options, FALSE);
+      if (temperrorcode != 0) return FALSE;
+      ptr++;    /* For compatibility */
+      }
+    /* Fall through */
+
+    case ESC_p:
+    case ESC_P:
+      {
+      int ptype, pdata, errorcodeptr;
+      BOOL negated;
+
+      ptr--;      /* Make ptr point at the p or P */
+      ptype = get_ucp(&ptr, &negated, &pdata, &errorcodeptr);
+      if (ptype < 0) return FALSE;
+      ptr++;      /* Point past the final curly ket */
+
+      /* If the property item is optional, we have to give up. (When generated
+      from \d etc by PCRE_UCP, this test will have been applied much earlier,
+      to the original \d etc. At this point, ptr will point to a zero byte. */
+
+      if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK ||
+        strncmp((char *)ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0)
+          return FALSE;
+
+      /* Do the property check. */
+
+      return check_char_prop(c, ptype, pdata, (next == -ESC_P) != negated);
+      }
+#endif
+
     default:
     return FALSE;
     }
 
+  /* In principle, support for Unicode properties should be integrated here as
+  well. It means re-organizing the above code so as to get hold of the property
+  values before switching on the op-code. However, I wonder how many patterns
+  combine ASCII \d etc with Unicode properties? (Note that if PCRE_UCP is set,
+  these op-codes are never generated.) */
+
   case OP_DIGIT:
   return next == -ESC_D || next == -ESC_s || next == -ESC_W ||
-         next == -ESC_h || next == -ESC_v;
+         next == -ESC_h || next == -ESC_v || next == -ESC_R;
 
   case OP_NOT_DIGIT:
   return next == -ESC_d;
 
   case OP_WHITESPACE:
-  return next == -ESC_S || next == -ESC_d || next == -ESC_w;
+  return next == -ESC_S || next == -ESC_d || next == -ESC_w || next == -ESC_R;
 
   case OP_NOT_WHITESPACE:
   return next == -ESC_s || next == -ESC_h || next == -ESC_v;
 
   case OP_HSPACE:
-  return next == -ESC_S || next == -ESC_H || next == -ESC_d || next == -ESC_w;
+  return next == -ESC_S || next == -ESC_H || next == -ESC_d ||
+         next == -ESC_w || next == -ESC_v || next == -ESC_R;
 
   case OP_NOT_HSPACE:
   return next == -ESC_h;
 
   /* Can't have \S in here because VT matches \S (Perl anomaly) */
+  case OP_ANYNL:
   case OP_VSPACE:
   return next == -ESC_V || next == -ESC_d || next == -ESC_w;
 
   case OP_NOT_VSPACE:
-  return next == -ESC_v;
+  return next == -ESC_v || next == -ESC_R;
 
   case OP_WORDCHAR:
-  return next == -ESC_W || next == -ESC_s || next == -ESC_h || next == -ESC_v;
+  return next == -ESC_W || next == -ESC_s || next == -ESC_h ||
+         next == -ESC_v || next == -ESC_R;
 
   case OP_NOT_WORDCHAR:
   return next == -ESC_w || next == -ESC_d;
@@ -2685,6 +2922,7 @@ BOOL inescq = FALSE;
 BOOL groupsetfirstbyte = FALSE;
 const uschar *ptr = *ptrptr;
 const uschar *tempptr;
+const uschar *nestptr = NULL;
 uschar *previous = NULL;
 uschar *previous_callout = NULL;
 uschar *save_hwm = NULL;
@@ -2755,6 +2993,16 @@ for (;; ptr++)
 
   c = *ptr;
 
+  /* If we are at the end of a nested substitution, revert to the outer level
+  string. Nesting only happens one level deep. */
+
+  if (c == 0 && nestptr != NULL)
+    {
+    ptr = nestptr;
+    nestptr = NULL;
+    c = *ptr;
+    }
+
   /* If we are in the pre-compile phase, accumulate the length used for the
   previous cycle of this loop. */
 
@@ -2785,7 +3033,7 @@ for (;; ptr++)
       goto FAILED;
       }
 
-    *lengthptr += code - last_code;
+    *lengthptr += (int)(code - last_code);
     DPRINTF(("length=%d added %d c=%c\n", *lengthptr, code - last_code, c));
 
     /* If "previous" is set and it is not at the start of the work space, move
@@ -2903,7 +3151,7 @@ for (;; ptr++)
         *errorcodeptr = ERR20;
         goto FAILED;
         }
-      *lengthptr += code - last_code;   /* To include callout length */
+      *lengthptr += (int)(code - last_code);   /* To include callout length */
       DPRINTF((">> end branch\n"));
       }
     return TRUE;
@@ -3108,7 +3356,7 @@ for (;; ptr++)
           ptr++;
           }
 
-        posix_class = check_posix_name(ptr, tempptr - ptr);
+        posix_class = check_posix_name(ptr, (int)(tempptr - ptr));
         if (posix_class < 0)
           {
           *errorcodeptr = ERR30;
@@ -3122,10 +3370,25 @@ for (;; ptr++)
         if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
           posix_class = 0;
 
-        /* We build the bit map for the POSIX class in a chunk of local store
-        because we may be adding and subtracting from it, and we don't want to
-        subtract bits that may be in the main map already. At the end we or the
-        result into the bit map that is being built. */
+        /* When PCRE_UCP is set, some of the POSIX classes are converted to
+        different escape sequences that use Unicode properties. */
+
+#ifdef SUPPORT_UCP
+        if ((options & PCRE_UCP) != 0)
+          {
+          int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0);
+          if (posix_substitutes[pc] != NULL)
+            {
+            nestptr = tempptr + 1;
+            ptr = posix_substitutes[pc] - 1;
+            continue;
+            }
+          }
+#endif
+        /* In the non-UCP case, we build the bit map for the POSIX class in a
+        chunk of local store because we may be adding and subtracting from it,
+        and we don't want to subtract bits that may be in the main map already.
+        At the end we or the result into the bit map that is being built. */
 
         posix_class *= 3;
 
@@ -3169,19 +3432,18 @@ for (;; ptr++)
 
       /* Backslash may introduce a single character, or it may introduce one
       of the specials, which just set a flag. The sequence \b is a special
-      case. Inside a class (and only there) it is treated as backspace.
-      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_charcount bigger than one. */
+      case. Inside a class (and only there) it is treated as backspace. We
+      assume that other escapes have more than one character in them, so set
+      class_charcount bigger than one. Unrecognized escapes fall through and
+      are either treated as literal characters (by default), or are faulted if
+      PCRE_EXTRA is set. */
 
       if (c == CHAR_BACKSLASH)
         {
         c = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
         if (*errorcodeptr != 0) goto FAILED;
 
-        if (-c == ESC_b) c = CHAR_BS;       /* \b is backspace in a class */
-        else if (-c == ESC_X) c = CHAR_X;   /* \X is literal X in a class */
-        else if (-c == ESC_R) c = CHAR_R;   /* \R is literal R in a class */
+        if (-c == ESC_b) c = CHAR_BS;    /* \b is backspace in a class */
         else if (-c == ESC_Q)            /* Handle start of quoted string */
           {
           if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
@@ -3198,10 +3460,20 @@ for (;; ptr++)
           register const uschar *cbits = cd->cbits;
           class_charcount += 2;     /* Greater than 1 is what matters */
 
-          /* Save time by not doing this in the pre-compile phase. */
-
-          if (lengthptr == NULL) switch (-c)
+          switch (-c)
             {
+#ifdef SUPPORT_UCP
+            case ESC_du:     /* These are the values given for \d etc */
+            case ESC_DU:     /* when PCRE_UCP is set. We replace the */
+            case ESC_wu:     /* escape sequence with an appropriate \p */
+            case ESC_WU:     /* or \P to test Unicode properties instead */
+            case ESC_su:     /* of the default ASCII testing. */
+            case ESC_SU:
+            nestptr = ptr;
+            ptr = substitutes[-c - ESC_DU] - 1;  /* Just before substitute */
+            class_charcount -= 2;                /* Undo! */
+            continue;
+#endif
             case ESC_d:
             for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
             continue;
@@ -3231,20 +3503,7 @@ for (;; ptr++)
             classbits[1] |= 0x08;    /* Perl 5.004 onwards omits VT from \s */
             continue;
 
-            default:    /* Not recognized; fall through */
-            break;      /* Need "default" setting to stop compiler warning. */
-            }
-
-          /* In the pre-compile phase, just do the recognition. */
-
-          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)
-            {
+            case ESC_h:
             SETBIT(classbits, 0x09); /* VT */
             SETBIT(classbits, 0x20); /* SPACE */
             SETBIT(classbits, 0xa0); /* NSBP */
@@ -3268,10 +3527,8 @@ for (;; ptr++)
               }
 #endif
             continue;
-            }
 
-          if (-c == ESC_H)
-            {
+            case ESC_H:
             for (c = 0; c < 32; c++)
               {
               int x = 0xff;
@@ -3313,10 +3570,8 @@ for (;; ptr++)
               }
 #endif
             continue;
-            }
 
-          if (-c == ESC_v)
-            {
+            case ESC_v:
             SETBIT(classbits, 0x0a); /* LF */
             SETBIT(classbits, 0x0b); /* VT */
             SETBIT(classbits, 0x0c); /* FF */
@@ -3332,10 +3587,8 @@ for (;; ptr++)
               }
 #endif
             continue;
-            }
 
-          if (-c == ESC_V)
-            {
+            case ESC_V:
             for (c = 0; c < 32; c++)
               {
               int x = 0xff;
@@ -3365,38 +3618,38 @@ for (;; ptr++)
               }
 #endif
             continue;
-            }
-
-          /* We need to deal with \P and \p in both phases. */
 
 #ifdef SUPPORT_UCP
-          if (-c == ESC_p || -c == ESC_P)
-            {
-            BOOL negated;
-            int pdata;
-            int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
-            if (ptype < 0) goto FAILED;
-            class_utf8 = TRUE;
-            *class_utf8data++ = ((-c == ESC_p) != negated)?
-              XCL_PROP : XCL_NOTPROP;
-            *class_utf8data++ = ptype;
-            *class_utf8data++ = pdata;
-            class_charcount -= 2;   /* Not a < 256 character */
-            continue;
-            }
+            case ESC_p:
+            case ESC_P:
+              {
+              BOOL negated;
+              int pdata;
+              int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
+              if (ptype < 0) goto FAILED;
+              class_utf8 = TRUE;
+              *class_utf8data++ = ((-c == ESC_p) != negated)?
+                XCL_PROP : XCL_NOTPROP;
+              *class_utf8data++ = ptype;
+              *class_utf8data++ = pdata;
+              class_charcount -= 2;   /* Not a < 256 character */
+              continue;
+              }
 #endif
-          /* Unrecognized escapes are faulted if PCRE is running in its
-          strict mode. By default, for compatibility with Perl, they are
-          treated as literals. */
+            /* Unrecognized escapes are faulted if PCRE is running in its
+            strict mode. By default, for compatibility with Perl, they are
+            treated as literals. */
 
-          if ((options & PCRE_EXTRA) != 0)
-            {
-            *errorcodeptr = ERR7;
-            goto FAILED;
+            default:
+            if ((options & PCRE_EXTRA) != 0)
+              {
+              *errorcodeptr = ERR7;
+              goto FAILED;
+              }
+            class_charcount -= 2;  /* Undo the default count from above */
+            c = *ptr;              /* Get the final character and fall through */
+            break;
             }
-
-          class_charcount -= 2;  /* Undo the default count from above */
-          c = *ptr;              /* Get the final character and fall through */
           }
 
         /* Fall through if we have a single character (c >= 0). This may be
@@ -3466,14 +3719,11 @@ for (;; ptr++)
           d = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
           if (*errorcodeptr != 0) goto FAILED;
 
-          /* \b is backspace; \X is literal X; \R is literal R; any other
-          special means the '-' was literal */
+          /* \b is backspace; any other special means the '-' was literal */
 
           if (d < 0)
             {
-            if (d == -ESC_b) d = CHAR_BS;
-            else if (d == -ESC_X) d = CHAR_X;
-            else if (d == -ESC_R) d = CHAR_R; else
+            if (d == -ESC_b) d = CHAR_BS; else
               {
               ptr = oldptr;
               goto LONE_SINGLE_CHARACTER;  /* A few lines below */
@@ -3639,35 +3889,23 @@ for (;; ptr++)
         }
       }
 
-    /* Loop until ']' reached. This "while" is the end of the "do" above. */
+    /* Loop until ']' reached. This "while" is the end of the "do" far above.
+    If we are at the end of an internal nested string, revert to the outer
+    string. */
+
+    while (((c = *(++ptr)) != 0 ||
+           (nestptr != NULL &&
+             (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != 0)) &&
+           (c != CHAR_RIGHT_SQUARE_BRACKET || inescq));
 
-    while ((c = *(++ptr)) != 0 && (c != CHAR_RIGHT_SQUARE_BRACKET || inescq));
+    /* Check for missing terminating ']' */
 
-    if (c == 0)                          /* Missing terminating ']' */
+    if (c == 0)
       {
       *errorcodeptr = ERR6;
       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. 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
@@ -3731,13 +3969,14 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 
     /* If there are characters with values > 255, we have to compile an
     extended class, with its own opcode, unless there was a negated special
-    such as \S in the class, because in that case all characters > 255 are in
-    the class, so any that were explicitly given as well can be ignored. If
-    (when there are explicit characters > 255 that must be listed) there are no
-    characters < 256, we can omit the bitmap in the actual compiled code. */
+    such as \S in the class, and PCRE_UCP is not set, because in that case all
+    characters > 255 are in the class, so any that were explicitly given as
+    well can be ignored. If (when there are explicit characters > 255 that must
+    be listed) there are no characters < 256, we can omit the bitmap in the
+    actual compiled code. */
 
 #ifdef SUPPORT_UTF8
-    if (class_utf8 && !should_flip_negation)
+    if (class_utf8 && (!should_flip_negation || (options & PCRE_UCP) != 0))
       {
       *class_utf8data++ = XCL_END;    /* Marks the end of extra data */
       *code++ = OP_XCLASS;
@@ -3763,10 +4002,11 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
       }
 #endif
 
-    /* If there are no characters > 255, set the opcode to OP_CLASS or
-    OP_NCLASS, depending on whether the whole class was negated and whether
-    there were negative specials such as \S in the class. Then copy the 32-byte
-    map into the code vector, negating it if necessary. */
+    /* If there are no characters > 255, or they are all to be included or
+    excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the
+    whole class was negated and whether there were negative specials such as \S
+    (non-UCP) in the class. Then copy the 32-byte map into the code vector,
+    negating it if necessary. */
 
     *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;
     if (negate_class)
@@ -3890,8 +4130,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 
       if (!possessive_quantifier &&
           repeat_max < 0 &&
-          check_auto_possessive(*previous, c, utf8, utf8_char, ptr + 1,
-            options, cd))
+          check_auto_possessive(previous, utf8, ptr + 1, options, cd))
         {
         repeat_type = 0;    /* Force greedy */
         possessive_quantifier = TRUE;
@@ -3912,7 +4151,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
       c = previous[1];
       if (!possessive_quantifier &&
           repeat_max < 0 &&
-          check_auto_possessive(OP_NOT, c, utf8, NULL, ptr + 1, options, cd))
+          check_auto_possessive(previous, utf8, ptr + 1, options, cd))
         {
         repeat_type = 0;    /* Force greedy */
         possessive_quantifier = TRUE;
@@ -3936,7 +4175,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 
       if (!possessive_quantifier &&
           repeat_max < 0 &&
-          check_auto_possessive(c, 0, utf8, NULL, ptr + 1, options, cd))
+          check_auto_possessive(previous, utf8, ptr + 1, options, cd))
         {
         repeat_type = 0;    /* Force greedy */
         possessive_quantifier = TRUE;
@@ -4146,7 +4385,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
       {
       register int i;
       int ketoffset = 0;
-      int len = code - previous;
+      int len = (int)(code - previous);
       uschar *bralink = NULL;
 
       /* Repeating a DEFINE group is pointless */
@@ -4167,7 +4406,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
         {
         register uschar *ket = previous;
         do ket += GET(ket, 1); while (*ket != OP_KET);
-        ketoffset = code - ket;
+        ketoffset = (int)(code - ket);
         }
 
       /* The case of a zero minimum is special because of the need to stick
@@ -4235,7 +4474,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
           /* 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;
+          offset = (bralink == NULL)? 0 : (int)(previous - bralink);
           bralink = previous;
           PUTINC(previous, 0, offset);
           }
@@ -4344,7 +4583,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
             {
             int offset;
             *code++ = OP_BRA;
-            offset = (bralink == NULL)? 0 : code - bralink;
+            offset = (bralink == NULL)? 0 : (int)(code - bralink);
             bralink = code;
             PUTINC(code, 0, offset);
             }
@@ -4365,7 +4604,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
         while (bralink != NULL)
           {
           int oldlinkoffset;
-          int offset = code - bralink + 1;
+          int offset = (int)(code - bralink + 1);
           uschar *bra = code - offset;
           oldlinkoffset = GET(bra, 1);
           bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
@@ -4453,7 +4692,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 #endif
         }
 
-      len = code - tempcode;
+      len = (int)(code - tempcode);
       if (len > 0) switch (*tempcode)
         {
         case OP_STAR:  *tempcode = OP_POSSTAR; break;
@@ -4512,24 +4751,34 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 
     /* First deal with various "verbs" that can be introduced by '*'. */
 
-    if (*(++ptr) == CHAR_ASTERISK && (cd->ctypes[ptr[1]] & ctype_letter) != 0)
+    if (*(++ptr) == CHAR_ASTERISK &&
+         ((cd->ctypes[ptr[1]] & ctype_letter) != 0 || ptr[1] == ':'))
       {
       int i, namelen;
+      int arglen = 0;
       const char *vn = verbnames;
-      const uschar *name = ++ptr;
+      const uschar *name = ptr + 1;
+      const uschar *arg = NULL;
       previous = NULL;
       while ((cd->ctypes[*++ptr] & ctype_letter) != 0) {};
+      namelen = (int)(ptr - name);
+
       if (*ptr == CHAR_COLON)
         {
-        *errorcodeptr = ERR59;   /* Not supported */
-        goto FAILED;
+        arg = ++ptr;
+        while ((cd->ctypes[*ptr] & (ctype_letter|ctype_digit)) != 0
+          || *ptr == '_') ptr++;
+        arglen = (int)(ptr - arg);
         }
+
       if (*ptr != CHAR_RIGHT_PARENTHESIS)
         {
         *errorcodeptr = ERR60;
         goto FAILED;
         }
-      namelen = ptr - name;
+
+      /* Scan the table of verb names */
+
       for (i = 0; i < verbcount; i++)
         {
         if (namelen == verbs[i].len &&
@@ -4547,13 +4796,41 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
               PUT2INC(code, 0, oc->number);
               }
             }
-          *code++ = verbs[i].op;
-          break;
+
+          /* Handle the cases with/without an argument */
+
+          if (arglen == 0)
+            {
+            if (verbs[i].op < 0)   /* Argument is mandatory */
+              {
+              *errorcodeptr = ERR66;
+              goto FAILED;
+              }
+            *code++ = verbs[i].op;
+            }
+
+          else
+            {
+            if (verbs[i].op_arg < 0)   /* Argument is forbidden */
+              {
+              *errorcodeptr = ERR59;
+              goto FAILED;
+              }
+            *code++ = verbs[i].op_arg;
+            *code++ = arglen;
+            memcpy(code, arg, arglen);
+            code += arglen;
+            *code++ = 0;
+            }
+
+          break;  /* Found verb, exit loop */
           }
+
         vn += verbs[i].len + 1;
         }
-      if (i < verbcount) continue;
-      *errorcodeptr = ERR60;
+
+      if (i < verbcount) continue;    /* Successfully handled a verb */
+      *errorcodeptr = ERR60;          /* Verb not recognized */
       goto FAILED;
       }
 
@@ -4672,7 +4949,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
               recno * 10 + *ptr - CHAR_0 : -1;
           ptr++;
           }
-        namelen = ptr - name;
+        namelen = (int)(ptr - name);
 
         if ((terminator > 0 && *ptr++ != terminator) ||
             *ptr++ != CHAR_RIGHT_PARENTHESIS)
@@ -4868,8 +5145,8 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
             goto FAILED;
             }
           *code++ = n;
-          PUT(code, 0, ptr - cd->start_pattern + 1);  /* Pattern offset */
-          PUT(code, LINK_SIZE, 0);                    /* Default length */
+          PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */
+          PUT(code, LINK_SIZE, 0);                          /* Default length */
           code += 2 * LINK_SIZE;
           }
         previous = NULL;
@@ -4902,7 +5179,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
           name = ++ptr;
 
           while ((cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
-          namelen = ptr - name;
+          namelen = (int)(ptr - name);
 
           /* In the pre-compile phase, just do a syntax check. */
 
@@ -5032,7 +5309,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
         NAMED_REF_OR_RECURSE:
         name = ++ptr;
         while ((cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
-        namelen = ptr - name;
+        namelen = (int)(ptr - name);
 
         /* In the pre-compile phase, do a syntax check and set a dummy
         reference number. */
@@ -5201,7 +5478,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
               of the group. */
 
               called = cd->start_code + recno;
-              PUTINC(cd->hwm, 0, code + 2 + LINK_SIZE - cd->start_code);
+              PUTINC(cd->hwm, 0, (int)(code + 2 + LINK_SIZE - cd->start_code));
               }
 
             /* If not a forward reference, and the subpattern is still open,
@@ -5225,7 +5502,7 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
           code += 1 + LINK_SIZE;
 
           *code = OP_RECURSE;
-          PUT(code, 1, called - cd->start_code);
+          PUT(code, 1, (int)(called - cd->start_code));
           code += 1 + LINK_SIZE;
 
           *code = OP_KET;
@@ -5336,8 +5613,8 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
         }     /* End of switch for character following (? */
       }       /* End of (? handling */
 
-    /* Opening parenthesis not followed by '?'. If PCRE_NO_AUTO_CAPTURE is set,
-    all unadorned brackets become non-capturing and behave like (?:...)
+    /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE
+    is set, all unadorned brackets become non-capturing and behave like (?:...)
     brackets. */
 
     else if ((options & PCRE_NO_AUTO_CAPTURE) != 0)
@@ -5529,11 +5806,12 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 
     /* ===================================================================*/
     /* Handle metasequences 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. */
+    are arranged to be the negation of the corresponding OP_values in the
+    default case when PCRE_UCP is not set. For the back references, the values
+    are ESC_REF plus the reference number. Only back references and those types
+    that consume a character may be repeated. We can test for values between
+    ESC_b and ESC_Z for the latter; this may have to change if any new ones are
+    ever created. */
 
     case CHAR_BACKSLASH:
     tempptr = ptr;
@@ -5693,12 +5971,24 @@ we set the flag only if there is a literal "\r" or "\n" in the class. */
 #endif
 
       /* For the rest (including \X when Unicode properties are supported), we
-      can obtain the OP value by negating the escape value. */
+      can obtain the OP value by negating the escape value in the default
+      situation when PCRE_UCP is not set. When it *is* set, we substitute
+      Unicode property tests. */
 
       else
         {
-        previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
-        *code++ = -c;
+#ifdef SUPPORT_UCP
+        if (-c >= ESC_DU && -c <= ESC_wu)
+          {
+          nestptr = ptr + 1;                   /* Where to resume */
+          ptr = substitutes[-c - ESC_DU] - 1;  /* Just before substitute */
+          }
+        else
+#endif
+          {
+          previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
+          *code++ = -c;
+          }
         }
       continue;
       }
@@ -6030,7 +6320,7 @@ for (;;)
     {
     if (lengthptr == NULL)
       {
-      int branch_length = code - last_branch;
+      int branch_length = (int)(code - last_branch);
       do
         {
         int prev_length = GET(last_branch, 1);
@@ -6044,7 +6334,7 @@ for (;;)
     /* Fill in the ket */
 
     *code = OP_KET;
-    PUT(code, 1, code - start_bracket);
+    PUT(code, 1, (int)(code - start_bracket));
     code += 1 + LINK_SIZE;
 
     /* If it was a capturing subpattern, check to see if it contained any
@@ -6059,9 +6349,9 @@ for (;;)
           code - start_bracket);
         *start_bracket = OP_ONCE;
         code += 1 + LINK_SIZE;
-        PUT(start_bracket, 1, code - start_bracket);
+        PUT(start_bracket, 1, (int)(code - start_bracket));
         *code = OP_KET;
-        PUT(code, 1, code - start_bracket);
+        PUT(code, 1, (int)(code - start_bracket));
         code += 1 + LINK_SIZE;
         length += 2 + 2*LINK_SIZE;
         }
@@ -6116,7 +6406,7 @@ for (;;)
   else
     {
     *code = OP_ALT;
-    PUT(code, 1, code - last_branch);
+    PUT(code, 1, (int)(code - last_branch));
     bc.current_branch = last_branch = code;
     code += 1 + LINK_SIZE;
     }
@@ -6435,7 +6725,7 @@ int length = 1;  /* For final END opcode */
 int firstbyte, reqbyte, newline;
 int errorcode = 0;
 int skipatstart = 0;
-BOOL utf8 = (options & PCRE_UTF8) != 0;
+BOOL utf8;
 size_t size;
 uschar *code;
 const uschar *codestart;
@@ -6505,6 +6795,8 @@ while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&
 
   if (strncmp((char *)(ptr+skipatstart+2), STRING_UTF8_RIGHTPAR, 5) == 0)
     { skipatstart += 7; options |= PCRE_UTF8; continue; }
+  else if (strncmp((char *)(ptr+skipatstart+2), STRING_UCP_RIGHTPAR, 4) == 0)
+    { skipatstart += 6; options |= PCRE_UCP; continue; }
 
   if (strncmp((char *)(ptr+skipatstart+2), STRING_CR_RIGHTPAR, 3) == 0)
     { skipatstart += 5; newnl = PCRE_NEWLINE_CR; }
@@ -6529,6 +6821,8 @@ while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&
   else break;
   }
 
+utf8 = (options & PCRE_UTF8) != 0;
+
 /* Can't support UTF8 unless PCRE has been compiled to include the code. */
 
 #ifdef SUPPORT_UTF8
@@ -6546,6 +6840,16 @@ if (utf8)
   }
 #endif
 
+/* Can't support UCP unless PCRE has been compiled to include the code. */
+
+#ifndef SUPPORT_UCP
+if ((options & PCRE_UCP) != 0)
+  {
+  errorcode = ERR67;
+  goto PCRE_EARLY_ERROR_RETURN;
+  }
+#endif
+
 /* Check validity of \R options. */
 
 switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
@@ -6674,7 +6978,7 @@ 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->size = (int)size;
 re->options = cd->external_options;
 re->flags = cd->external_flags;
 re->dummy1 = 0;
@@ -6745,7 +7049,7 @@ while (errorcode == 0 && cd->hwm > cworkspace)
   recno = GET(codestart, offset);
   groupptr = _pcre_find_bracket(codestart, utf8, recno);
   if (groupptr == NULL) errorcode = ERR53;
-    else PUT(((uschar *)codestart), offset, groupptr - codestart);
+    else PUT(((uschar *)codestart), offset, (int)(groupptr - codestart));
   }
 
 /* Give an error if there's back reference to a non-existent capturing
@@ -6800,7 +7104,7 @@ if (errorcode != 0)
   {
   (pcre_free)(re);
   PCRE_EARLY_ERROR_RETURN:
-  *erroroffset = ptr - (const uschar *)pattern;
+  *erroroffset = (int)(ptr - (const uschar *)pattern);
   PCRE_EARLY_ERROR_RETURN2:
   *errorptr = find_error_text(errorcode);
   if (errorcodeptr != NULL) *errorcodeptr = errorcode;
index 4fe798e6b75627e520e612e9b479af646df16060..55883548c3620cb0cb806c8d77d90a7642d905fe 100644 (file)
@@ -69,10 +69,20 @@ defined PCRE_ERROR_xxx codes, which are all negative. */
 /* Special internal returns from the match() function. Make them sufficiently
 negative to avoid the external error codes. */
 
-#define MATCH_COMMIT       (-999)
-#define MATCH_PRUNE        (-998)
-#define MATCH_SKIP         (-997)
-#define MATCH_THEN         (-996)
+#define MATCH_ACCEPT       (-999)
+#define MATCH_COMMIT       (-998)
+#define MATCH_PRUNE        (-997)
+#define MATCH_SKIP         (-996)
+#define MATCH_SKIP_ARG     (-995)
+#define MATCH_THEN         (-994)
+
+/* This is a convenience macro for code that occurs many times. */
+
+#define MRRETURN(ra) \
+  { \
+  md->mark = markptr; \
+  RRETURN(ra); \
+  }
 
 /* Maximum number of ints of offset to save on the stack for recursive calls.
 If the offset vector is bigger, malloc is used. This should be a multiple of 3,
@@ -243,7 +253,8 @@ enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM6,  RM7,  RM8,  RM9,  RM10,
        RM21,  RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
        RM31,  RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,
        RM41,  RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,
-       RM51,  RM52, RM53, RM54 };
+       RM51,  RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,
+       RM61,  RM62 };
 
 /* These versions of the macros use the stack, as normal. There are debugging
 versions and production versions. Note that the "rw" argument of RMATCH isn't
@@ -282,6 +293,7 @@ argument of match(), which never changes. */
 #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\
   {\
   heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\
+  if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
   frame->Xwhere = rw; \
   newframe->Xeptr = ra;\
   newframe->Xecode = rb;\
@@ -302,9 +314,9 @@ argument of match(), which never changes. */
 
 #define RRETURN(ra)\
   {\
-  heapframe *newframe = frame;\
-  frame = newframe->Xprevframe;\
-  (pcre_stack_free)(newframe);\
+  heapframe *oldframe = frame;\
+  frame = oldframe->Xprevframe;\
+  (pcre_stack_free)(oldframe);\
   if (frame != NULL)\
     {\
     rrc = ra;\
@@ -411,14 +423,14 @@ the subject. */
   if (md->partial != 0 && eptr >= md->end_subject && eptr > mstart)\
     {\
     md->hitend = TRUE;\
-    if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);\
+    if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL);\
     }
 
 #define SCHECK_PARTIAL()\
   if (md->partial != 0 && eptr > mstart)\
     {\
     md->hitend = TRUE;\
-    if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);\
+    if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL);\
     }
 
 
@@ -446,13 +458,14 @@ Arguments:
 
 Returns:       MATCH_MATCH if matched            )  these values are >= 0
                MATCH_NOMATCH if failed to match  )
+               a negative MATCH_xxx value for PRUNE, SKIP, etc
                a negative PCRE_ERROR_xxx value if aborted by an error condition
                  (e.g. stopped by repeated call or recursion limit)
 */
 
 static int
-match(REGISTER USPTR eptr, REGISTER const uschar *ecode, USPTR mstart, USPTR
-  markptr, int offset_top, match_data *md, unsigned long int ims,
+match(REGISTER USPTR eptr, REGISTER const uschar *ecode, USPTR mstart,
+  const uschar *markptr, int offset_top, match_data *md, unsigned long int ims,
   eptrblock *eptrb, int flags, unsigned int rdepth)
 {
 /* These variables do not need to be preserved over recursion in this function,
@@ -474,6 +487,7 @@ heap whenever RMATCH() does a "recursion". See the macro definitions above. */
 
 #ifdef NO_RECURSE
 heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe));
+if (frame == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
 frame->Xprevframe = NULL;            /* Marks the top level */
 
 /* Copy in the original argument variables */
@@ -669,32 +683,81 @@ for (;;)
 
   switch(op)
     {
+    case OP_MARK:
+    markptr = ecode + 2;
+    RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
+      ims, eptrb, flags, RM55);
+
+    /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an
+    argument, and we must check whether that argument matches this MARK's
+    argument. It is passed back in md->start_match_ptr (an overloading of that
+    variable). If it does match, we reset that variable to the current subject
+    position and return MATCH_SKIP. Otherwise, pass back the return code
+    unaltered. */
+
+    if (rrc == MATCH_SKIP_ARG &&
+        strcmp((char *)markptr, (char *)(md->start_match_ptr)) == 0)
+      {
+      md->start_match_ptr = eptr;
+      RRETURN(MATCH_SKIP);
+      }
+
+    if (md->mark == NULL) md->mark = markptr;
+    RRETURN(rrc);
+
     case OP_FAIL:
-    RRETURN(MATCH_NOMATCH);
+    MRRETURN(MATCH_NOMATCH);
+
+    case OP_COMMIT:
+    RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
+      ims, eptrb, flags, RM52);
+    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+    MRRETURN(MATCH_COMMIT);
 
     case OP_PRUNE:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
       ims, eptrb, flags, RM51);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-    RRETURN(MATCH_PRUNE);
+    MRRETURN(MATCH_PRUNE);
 
-    case OP_COMMIT:
-    RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
-      ims, eptrb, flags, RM52);
+    case OP_PRUNE_ARG:
+    RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
+      ims, eptrb, flags, RM56);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-    RRETURN(MATCH_COMMIT);
+    md->mark = ecode + 2;
+    RRETURN(MATCH_PRUNE);
 
     case OP_SKIP:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
       ims, eptrb, flags, RM53);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);
     md->start_match_ptr = eptr;   /* Pass back current position */
-    RRETURN(MATCH_SKIP);
+    MRRETURN(MATCH_SKIP);
+
+    case OP_SKIP_ARG:
+    RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
+      ims, eptrb, flags, RM57);
+    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+
+    /* Pass back the current skip name by overloading md->start_match_ptr and
+    returning the special MATCH_SKIP_ARG return code. This will either be
+    caught by a matching MARK, or get to the top, where it is treated the same
+    as PRUNE. */
+
+    md->start_match_ptr = ecode + 2;
+    RRETURN(MATCH_SKIP_ARG);
 
     case OP_THEN:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
       ims, eptrb, flags, RM54);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+    MRRETURN(MATCH_THEN);
+
+    case OP_THEN_ARG:
+    RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
+      ims, eptrb, flags, RM58);
+    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+    md->mark = ecode + 2;
     RRETURN(MATCH_THEN);
 
     /* Handle a capturing bracket. If there is space in the offset vector, save
@@ -731,7 +794,8 @@ for (;;)
       save_capture_last = md->capture_last;
 
       DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
-      md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
+      md->offset_vector[md->offset_end - number] =
+        (int)(eptr - md->start_subject);
 
       flags = (op == OP_SCBRA)? match_cbegroup : 0;
       do
@@ -750,6 +814,7 @@ for (;;)
       md->offset_vector[offset+1] = save_offset2;
       md->offset_vector[md->offset_end - number] = save_offset3;
 
+      if (rrc != MATCH_THEN) md->mark = markptr;
       RRETURN(MATCH_NOMATCH);
       }
 
@@ -789,6 +854,7 @@ for (;;)
 
         RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
           eptrb, flags, RM48);
+        if (rrc == MATCH_NOMATCH) md->mark = markptr;
         RRETURN(rrc);
         }
 
@@ -824,15 +890,15 @@ for (;;)
         cb.callout_number   = ecode[LINK_SIZE+2];
         cb.offset_vector    = md->offset_vector;
         cb.subject          = (PCRE_SPTR)md->start_subject;
-        cb.subject_length   = md->end_subject - md->start_subject;
-        cb.start_match      = mstart - md->start_subject;
-        cb.current_position = eptr - md->start_subject;
+        cb.subject_length   = (int)(md->end_subject - md->start_subject);
+        cb.start_match      = (int)(mstart - md->start_subject);
+        cb.current_position = (int)(eptr - md->start_subject);
         cb.pattern_position = GET(ecode, LINK_SIZE + 3);
         cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE);
         cb.capture_top      = offset_top/2;
         cb.capture_last     = md->capture_last;
         cb.callout_data     = md->callout_data;
-        if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH);
+        if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH);
         if (rrc < 0) RRETURN(rrc);
         }
       ecode += _pcre_OP_lengths[OP_CALLOUT];
@@ -1052,7 +1118,7 @@ for (;;)
       {
       md->offset_vector[offset] =
         md->offset_vector[md->offset_end - number];
-      md->offset_vector[offset+1] = eptr - md->start_subject;
+      md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
       if (offset_top <= offset) offset_top = offset + 2;
       }
     ecode += 3;
@@ -1087,14 +1153,19 @@ for (;;)
         (md->notempty ||
           (md->notempty_atstart &&
             mstart == md->start_subject + md->start_offset)))
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
 
     /* Otherwise, we have a match. */
 
     md->end_match_ptr = eptr;           /* Record where we ended */
     md->end_offset_top = offset_top;    /* and how many extracts were taken */
     md->start_match_ptr = mstart;       /* and the start (\K can modify) */
-    RRETURN(MATCH_MATCH);
+
+    /* For some reason, the macros don't work properly if an expression is
+    given as the argument to MRRETURN when the heap is in use. */
+
+    rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT;
+    MRRETURN(rrc);
 
     /* Change option settings */
 
@@ -1116,7 +1187,7 @@ for (;;)
       {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
         RM4);
-      if (rrc == MATCH_MATCH)
+      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
         {
         mstart = md->start_match_ptr;   /* In case \K reset it */
         break;
@@ -1125,7 +1196,7 @@ for (;;)
       ecode += GET(ecode, 1);
       }
     while (*ecode == OP_ALT);
-    if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);
+    if (*ecode == OP_KET) MRRETURN(MATCH_NOMATCH);
 
     /* If checking an assertion for a condition, return MATCH_MATCH. */
 
@@ -1149,7 +1220,7 @@ for (;;)
       {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
         RM5);
-      if (rrc == MATCH_MATCHRRETURN(MATCH_NOMATCH);
+      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) MRRETURN(MATCH_NOMATCH);
       if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT)
         {
         do ecode += GET(ecode,1); while (*ecode == OP_ALT);
@@ -1178,7 +1249,7 @@ for (;;)
       while (i-- > 0)
         {
         eptr--;
-        if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
+        if (eptr < md->start_subject) MRRETURN(MATCH_NOMATCH);
         BACKCHAR(eptr);
         }
       }
@@ -1189,7 +1260,7 @@ for (;;)
 
       {
       eptr -= GET(ecode, 1);
-      if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
+      if (eptr < md->start_subject) MRRETURN(MATCH_NOMATCH);
       }
 
     /* Save the earliest consulted character, then skip to next op code */
@@ -1210,15 +1281,15 @@ for (;;)
       cb.callout_number   = ecode[1];
       cb.offset_vector    = md->offset_vector;
       cb.subject          = (PCRE_SPTR)md->start_subject;
-      cb.subject_length   = md->end_subject - md->start_subject;
-      cb.start_match      = mstart - md->start_subject;
-      cb.current_position = eptr - md->start_subject;
+      cb.subject_length   = (int)(md->end_subject - md->start_subject);
+      cb.start_match      = (int)(mstart - md->start_subject);
+      cb.current_position = (int)(eptr - md->start_subject);
       cb.pattern_position = GET(ecode, 2);
       cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
       cb.capture_top      = offset_top/2;
       cb.capture_last     = md->capture_last;
       cb.callout_data     = md->callout_data;
-      if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH);
+      if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH);
       if (rrc < 0) RRETURN(rrc);
       }
     ecode += 2 + 2*LINK_SIZE;
@@ -1284,13 +1355,13 @@ for (;;)
         {
         RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,
           md, ims, eptrb, flags, RM6);
-        if (rrc == MATCH_MATCH)
+        if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
           {
           DPRINTF(("Recursion matched\n"));
           md->recursive = new_recursive.prevrec;
           if (new_recursive.offset_save != stacksave)
             (pcre_free)(new_recursive.offset_save);
-          RRETURN(MATCH_MATCH);
+          MRRETURN(MATCH_MATCH);
           }
         else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
           {
@@ -1311,7 +1382,7 @@ for (;;)
       md->recursive = new_recursive.prevrec;
       if (new_recursive.offset_save != stacksave)
         (pcre_free)(new_recursive.offset_save);
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     /* Control never reaches here */
 
@@ -1330,7 +1401,7 @@ for (;;)
     do
       {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7);
-      if (rrc == MATCH_MATCH)
+      if (rrc == MATCH_MATCH)  /* Note: _not_ MATCH_ACCEPT */
         {
         mstart = md->start_match_ptr;
         break;
@@ -1465,7 +1536,7 @@ for (;;)
       md->end_match_ptr = eptr;      /* For ONCE */
       md->end_offset_top = offset_top;
       md->start_match_ptr = mstart;
-      RRETURN(MATCH_MATCH);
+      MRRETURN(MATCH_MATCH);
       }
 
     /* For capturing groups we have to check the group number back at the start
@@ -1489,7 +1560,7 @@ for (;;)
         {
         md->offset_vector[offset] =
           md->offset_vector[md->offset_end - number];
-        md->offset_vector[offset+1] = eptr - md->start_subject;
+        md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
         if (offset_top <= offset) offset_top = offset + 2;
         }
 
@@ -1560,12 +1631,12 @@ for (;;)
     /* Start of subject unless notbol, or after internal newline if multiline */
 
     case OP_CIRC:
-    if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
+    if (md->notbol && eptr == md->start_subject) MRRETURN(MATCH_NOMATCH);
     if ((ims & PCRE_MULTILINE) != 0)
       {
       if (eptr != md->start_subject &&
           (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
       ecode++;
       break;
       }
@@ -1574,14 +1645,14 @@ for (;;)
     /* Start of subject assertion */
 
     case OP_SOD:
-    if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
+    if (eptr != md->start_subject) MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
     /* Start of match assertion */
 
     case OP_SOM:
-    if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
+    if (eptr != md->start_subject + md->start_offset) MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1599,20 +1670,20 @@ for (;;)
     if ((ims & PCRE_MULTILINE) != 0)
       {
       if (eptr < md->end_subject)
-        { if (!IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); }
+        { if (!IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); }
       else
-        { if (md->noteol) RRETURN(MATCH_NOMATCH); }
+        { if (md->noteol) MRRETURN(MATCH_NOMATCH); }
       ecode++;
       break;
       }
     else
       {
-      if (md->noteol) RRETURN(MATCH_NOMATCH);
+      if (md->noteol) MRRETURN(MATCH_NOMATCH);
       if (!md->endonly)
         {
         if (eptr != md->end_subject &&
             (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
         ecode++;
         break;
         }
@@ -1622,7 +1693,7 @@ for (;;)
     /* End of subject assertion (\z) */
 
     case OP_EOD:
-    if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);
+    if (eptr < md->end_subject) MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1631,7 +1702,7 @@ for (;;)
     case OP_EODN:
     if (eptr != md->end_subject &&
         (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1649,14 +1720,30 @@ for (;;)
 #ifdef SUPPORT_UTF8
       if (utf8)
         {
+        /* Get status of previous character */
+
         if (eptr == md->start_subject) prev_is_word = FALSE; else
           {
           USPTR lastptr = eptr - 1;
           while((*lastptr & 0xc0) == 0x80) lastptr--;
           if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
           GETCHAR(c, lastptr);
+#ifdef SUPPORT_UCP
+          if (md->use_ucp)
+            {
+            if (c == '_') prev_is_word = TRUE; else
+              {
+              int cat = UCD_CATEGORY(c);
+              prev_is_word = (cat == ucp_L || cat == ucp_N);
+              }
+            }
+          else
+#endif
           prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
           }
+
+        /* Get status of next character */
+
         if (eptr >= md->end_subject)
           {
           SCHECK_PARTIAL();
@@ -1665,47 +1752,89 @@ for (;;)
         else
           {
           GETCHAR(c, eptr);
+#ifdef SUPPORT_UCP
+          if (md->use_ucp)
+            {
+            if (c == '_') cur_is_word = TRUE; else
+              {
+              int cat = UCD_CATEGORY(c);
+              cur_is_word = (cat == ucp_L || cat == ucp_N);
+              }
+            }
+          else
+#endif
           cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
           }
         }
       else
 #endif
 
-      /* Not in UTF-8 mode */
+      /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for
+      consistency with the behaviour of \w we do use it in this case. */
 
         {
+        /* Get status of previous character */
+
         if (eptr == md->start_subject) prev_is_word = FALSE; else
           {
           if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1;
+#ifdef SUPPORT_UCP
+          if (md->use_ucp)
+            {
+            c = eptr[-1];
+            if (c == '_') prev_is_word = TRUE; else
+              {
+              int cat = UCD_CATEGORY(c);
+              prev_is_word = (cat == ucp_L || cat == ucp_N);
+              }
+            }
+          else
+#endif
           prev_is_word = ((md->ctypes[eptr[-1]] & ctype_word) != 0);
           }
+
+        /* Get status of next character */
+
         if (eptr >= md->end_subject)
           {
           SCHECK_PARTIAL();
           cur_is_word = FALSE;
           }
-        else cur_is_word = ((md->ctypes[*eptr] & ctype_word) != 0);
+        else
+#ifdef SUPPORT_UCP
+        if (md->use_ucp)
+          {
+          c = *eptr;
+          if (c == '_') cur_is_word = TRUE; else
+            {
+            int cat = UCD_CATEGORY(c);
+            cur_is_word = (cat == ucp_L || cat == ucp_N);
+            }
+          }
+        else
+#endif
+        cur_is_word = ((md->ctypes[*eptr] & ctype_word) != 0);
         }
 
       /* Now see if the situation is what we want */
 
       if ((*ecode++ == OP_WORD_BOUNDARY)?
            cur_is_word == prev_is_word : cur_is_word != prev_is_word)
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
       }
     break;
 
     /* Match a single character type; inline for speed */
 
     case OP_ANY:
-    if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+    if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH);
     /* Fall through */
 
     case OP_ALLANY:
     if (eptr++ >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
     ecode++;
@@ -1718,7 +1847,7 @@ for (;;)
     if (eptr++ >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     ecode++;
     break;
@@ -1727,7 +1856,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     if (
@@ -1736,7 +1865,7 @@ for (;;)
 #endif
        (md->ctypes[c] & ctype_digit) != 0
        )
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1744,7 +1873,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     if (
@@ -1753,7 +1882,7 @@ for (;;)
 #endif
        (md->ctypes[c] & ctype_digit) == 0
        )
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1761,7 +1890,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     if (
@@ -1770,7 +1899,7 @@ for (;;)
 #endif
        (md->ctypes[c] & ctype_space) != 0
        )
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1778,7 +1907,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     if (
@@ -1787,7 +1916,7 @@ for (;;)
 #endif
        (md->ctypes[c] & ctype_space) == 0
        )
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1795,7 +1924,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     if (
@@ -1804,7 +1933,7 @@ for (;;)
 #endif
        (md->ctypes[c] & ctype_word) != 0
        )
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1812,7 +1941,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     if (
@@ -1821,7 +1950,7 @@ for (;;)
 #endif
        (md->ctypes[c] & ctype_word) == 0
        )
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
 
@@ -1829,12 +1958,12 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     switch(c)
       {
-      default: RRETURN(MATCH_NOMATCH);
+      default: MRRETURN(MATCH_NOMATCH);
       case 0x000d:
       if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
       break;
@@ -1847,7 +1976,7 @@ for (;;)
       case 0x0085:
       case 0x2028:
       case 0x2029:
-      if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+      if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
       break;
       }
     ecode++;
@@ -1857,7 +1986,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     switch(c)
@@ -1882,7 +2011,7 @@ for (;;)
       case 0x202f:    /* NARROW NO-BREAK SPACE */
       case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
       case 0x3000:    /* IDEOGRAPHIC SPACE */
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     ecode++;
     break;
@@ -1891,12 +2020,12 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     switch(c)
       {
-      default: RRETURN(MATCH_NOMATCH);
+      default: MRRETURN(MATCH_NOMATCH);
       case 0x09:      /* HT */
       case 0x20:      /* SPACE */
       case 0xa0:      /* NBSP */
@@ -1925,7 +2054,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     switch(c)
@@ -1938,7 +2067,7 @@ for (;;)
       case 0x85:      /* NEL */
       case 0x2028:    /* LINE SEPARATOR */
       case 0x2029:    /* PARAGRAPH SEPARATOR */
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     ecode++;
     break;
@@ -1947,12 +2076,12 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
     switch(c)
       {
-      default: RRETURN(MATCH_NOMATCH);
+      default: MRRETURN(MATCH_NOMATCH);
       case 0x0a:      /* LF */
       case 0x0b:      /* VT */
       case 0x0c:      /* FF */
@@ -1974,7 +2103,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
       {
@@ -1983,31 +2112,63 @@ for (;;)
       switch(ecode[1])
         {
         case PT_ANY:
-        if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+        if (op == OP_NOTPROP) MRRETURN(MATCH_NOMATCH);
         break;
 
         case PT_LAMP:
         if ((prop->chartype == ucp_Lu ||
              prop->chartype == ucp_Ll ||
              prop->chartype == ucp_Lt) == (op == OP_NOTPROP))
-          RRETURN(MATCH_NOMATCH);
-         break;
+          MRRETURN(MATCH_NOMATCH);
+        break;
 
         case PT_GC:
         if ((ecode[2] != _pcre_ucp_gentype[prop->chartype]) == (op == OP_PROP))
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
         break;
 
         case PT_PC:
         if ((ecode[2] != prop->chartype) == (op == OP_PROP))
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
         break;
 
         case PT_SC:
         if ((ecode[2] != prop->script) == (op == OP_PROP))
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
+        break;
+
+        /* These are specials */
+
+        case PT_ALNUM:
+        if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
+             _pcre_ucp_gentype[prop->chartype] == ucp_N) == (op == OP_NOTPROP))
+          MRRETURN(MATCH_NOMATCH);
+        break;
+
+        case PT_SPACE:    /* Perl space */
+        if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
+             c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
+               == (op == OP_NOTPROP))
+          MRRETURN(MATCH_NOMATCH);
         break;
 
+        case PT_PXSPACE:  /* POSIX space */
+        if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
+             c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+             c == CHAR_FF || c == CHAR_CR)
+               == (op == OP_NOTPROP))
+          MRRETURN(MATCH_NOMATCH);
+        break;
+
+        case PT_WORD:
+        if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
+             _pcre_ucp_gentype[prop->chartype] == ucp_N ||
+             c == CHAR_UNDERSCORE) == (op == OP_NOTPROP))
+          MRRETURN(MATCH_NOMATCH);
+        break;
+
+        /* This should never occur */
+
         default:
         RRETURN(PCRE_ERROR_INTERNAL);
         }
@@ -2023,12 +2184,12 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     GETCHARINCTEST(c, eptr);
       {
       int category = UCD_CATEGORY(c);
-      if (category == ucp_M) RRETURN(MATCH_NOMATCH);
+      if (category == ucp_M) MRRETURN(MATCH_NOMATCH);
       while (eptr < md->end_subject)
         {
         int len = 1;
@@ -2073,7 +2234,7 @@ for (;;)
       referenced subpattern. */
 
       if (offset >= offset_top || md->offset_vector[offset] < 0)
-        length = (md->jscript_compat)? 0 : md->end_subject - eptr + 1;
+        length = (md->jscript_compat)? 0 : (int)(md->end_subject - eptr + 1);
       else
         length = md->offset_vector[offset+1] - md->offset_vector[offset];
 
@@ -2107,7 +2268,7 @@ for (;;)
         if (!match_ref(offset, eptr, length, md, ims))
           {
           CHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
         eptr += length;
         continue;              /* With the main loop */
@@ -2127,7 +2288,7 @@ for (;;)
         if (!match_ref(offset, eptr, length, md, ims))
           {
           CHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
         eptr += length;
         }
@@ -2145,11 +2306,11 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (!match_ref(offset, eptr, length, md, ims))
             {
             CHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           eptr += length;
           }
@@ -2176,7 +2337,7 @@ for (;;)
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           eptr -= length;
           }
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
       }
     /* Control never gets here */
@@ -2238,16 +2399,16 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           if (c > 255)
             {
-            if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
+            if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH);
             }
           else
             {
-            if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+            if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
             }
           }
         }
@@ -2260,10 +2421,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           c = *eptr++;
-          if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+          if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
           }
         }
 
@@ -2285,20 +2446,20 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINC(c, eptr);
             if (c > 255)
               {
-              if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
+              if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH);
               }
             else
               {
-              if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+              if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
               }
             }
           }
@@ -2310,14 +2471,14 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             c = *eptr++;
-            if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+            if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
             }
           }
         /* Control never gets here */
@@ -2383,7 +2544,7 @@ for (;;)
             }
           }
 
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
       }
     /* Control never gets here */
@@ -2435,10 +2596,10 @@ for (;;)
         if (eptr >= md->end_subject)
           {
           SCHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
         GETCHARINCTEST(c, eptr);
-        if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
+        if (!_pcre_xclass(c, data)) MRRETURN(MATCH_NOMATCH);
         }
 
       /* If max == min we can continue with the main loop without the
@@ -2455,14 +2616,14 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINCTEST(c, eptr);
-          if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
+          if (!_pcre_xclass(c, data)) MRRETURN(MATCH_NOMATCH);
           }
         /* Control never gets here */
         }
@@ -2491,7 +2652,7 @@ for (;;)
           if (eptr-- == pp) break;        /* Stop if tried at original pos */
           if (utf8) BACKCHAR(eptr);
           }
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
 
       /* Control never gets here */
@@ -2510,9 +2671,9 @@ for (;;)
       if (length > md->end_subject - eptr)
         {
         CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
-      while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);
+      while (length-- > 0) if (*ecode++ != *eptr++) MRRETURN(MATCH_NOMATCH);
       }
     else
 #endif
@@ -2522,9 +2683,9 @@ for (;;)
       if (md->end_subject - eptr < 1)
         {
         SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
-      if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
+      if (ecode[1] != *eptr++) MRRETURN(MATCH_NOMATCH);
       ecode += 2;
       }
     break;
@@ -2542,7 +2703,7 @@ for (;;)
       if (length > md->end_subject - eptr)
         {
         CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
 
       /* If the pattern character's value is < 128, we have only one byte, and
@@ -2550,7 +2711,7 @@ for (;;)
 
       if (fc < 128)
         {
-        if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
+        if (md->lcc[*ecode++] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
         }
 
       /* Otherwise we must pick up the subject character */
@@ -2569,7 +2730,7 @@ for (;;)
 #ifdef SUPPORT_UCP
           if (dc != UCD_OTHERCASE(fc))
 #endif
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           }
         }
       }
@@ -2581,9 +2742,9 @@ for (;;)
       if (md->end_subject - eptr < 1)
         {
         SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
-      if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
+      if (md->lcc[ecode[1]] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
       ecode += 2;
       }
     break;
@@ -2677,7 +2838,7 @@ for (;;)
           else
             {
             CHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           }
 
@@ -2689,7 +2850,7 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr <= md->end_subject - length &&
               memcmp(eptr, charptr, length) == 0) eptr += length;
 #ifdef SUPPORT_UCP
@@ -2700,7 +2861,7 @@ for (;;)
             else
               {
               CHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             }
           /* Control never gets here */
@@ -2731,7 +2892,7 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (eptr == pp) { RRETURN(MATCH_NOMATCH); }
+            if (eptr == pp) { MRRETURN(MATCH_NOMATCH); }
 #ifdef SUPPORT_UCP
             eptr--;
             BACKCHAR(eptr);
@@ -2774,9 +2935,9 @@ for (;;)
         if (eptr >= md->end_subject)
           {
           SCHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
-        if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
+        if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
         }
       if (min == max) continue;
       if (minimize)
@@ -2785,13 +2946,13 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
+          if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
           }
         /* Control never gets here */
         }
@@ -2817,7 +2978,7 @@ for (;;)
           eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
       /* Control never gets here */
       }
@@ -2831,9 +2992,9 @@ for (;;)
         if (eptr >= md->end_subject)
           {
           SCHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
-        if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
+        if (fc != *eptr++) MRRETURN(MATCH_NOMATCH);
         }
 
       if (min == max) continue;
@@ -2844,13 +3005,13 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
+          if (fc != *eptr++) MRRETURN(MATCH_NOMATCH);
           }
         /* Control never gets here */
         }
@@ -2875,7 +3036,7 @@ for (;;)
           eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
       }
     /* Control never gets here */
@@ -2887,7 +3048,7 @@ for (;;)
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     ecode++;
     GETCHARINCTEST(c, eptr);
@@ -2897,11 +3058,11 @@ for (;;)
       if (c < 256)
 #endif
       c = md->lcc[c];
-      if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH);
+      if (md->lcc[*ecode++] == c) MRRETURN(MATCH_NOMATCH);
       }
     else
       {
-      if (*ecode++ == c) RRETURN(MATCH_NOMATCH);
+      if (*ecode++ == c) MRRETURN(MATCH_NOMATCH);
       }
     break;
 
@@ -2995,11 +3156,11 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(d, eptr);
           if (d < 256) d = md->lcc[d];
-          if (fc == d) RRETURN(MATCH_NOMATCH);
+          if (fc == d) MRRETURN(MATCH_NOMATCH);
           }
         }
       else
@@ -3012,9 +3173,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
+          if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
           }
         }
 
@@ -3031,15 +3192,15 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINC(d, eptr);
             if (d < 256) d = md->lcc[d];
-            if (fc == d) RRETURN(MATCH_NOMATCH);
+            if (fc == d) MRRETURN(MATCH_NOMATCH);
             }
           }
         else
@@ -3050,13 +3211,13 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
+            if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
             }
           }
         /* Control never gets here */
@@ -3118,7 +3279,7 @@ for (;;)
             }
           }
 
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
       /* Control never gets here */
       }
@@ -3137,10 +3298,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(d, eptr);
-          if (fc == d) RRETURN(MATCH_NOMATCH);
+          if (fc == d) MRRETURN(MATCH_NOMATCH);
           }
         }
       else
@@ -3152,9 +3313,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
+          if (fc == *eptr++) MRRETURN(MATCH_NOMATCH);
           }
         }
 
@@ -3171,14 +3332,14 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINC(d, eptr);
-            if (fc == d) RRETURN(MATCH_NOMATCH);
+            if (fc == d) MRRETURN(MATCH_NOMATCH);
             }
           }
         else
@@ -3189,13 +3350,13 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
+            if (fc == *eptr++) MRRETURN(MATCH_NOMATCH);
             }
           }
         /* Control never gets here */
@@ -3256,7 +3417,7 @@ for (;;)
             }
           }
 
-        RRETURN(MATCH_NOMATCH);
+        MRRETURN(MATCH_NOMATCH);
         }
       }
     /* Control never gets here */
@@ -3350,13 +3511,13 @@ for (;;)
         switch(prop_type)
           {
           case PT_ANY:
-          if (prop_fail_result) RRETURN(MATCH_NOMATCH);
+          if (prop_fail_result) MRRETURN(MATCH_NOMATCH);
           for (i = 1; i <= min; i++)
             {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINCTEST(c, eptr);
             }
@@ -3368,14 +3529,14 @@ for (;;)
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == ucp_Lu ||
                  prop_chartype == ucp_Ll ||
                  prop_chartype == ucp_Lt) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           break;
 
@@ -3385,12 +3546,12 @@ for (;;)
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINCTEST(c, eptr);
             prop_category = UCD_CATEGORY(c);
             if ((prop_category == prop_value) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           break;
 
@@ -3400,12 +3561,12 @@ for (;;)
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == prop_value) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           break;
 
@@ -3415,15 +3576,84 @@ for (;;)
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINCTEST(c, eptr);
             prop_script = UCD_SCRIPT(c);
             if ((prop_script == prop_value) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           break;
 
+          case PT_ALNUM:
+          for (i = 1; i <= min; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_L || prop_category == ucp_N)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          break;
+
+          case PT_SPACE:    /* Perl space */
+          for (i = 1; i <= min; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          for (i = 1; i <= min; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          break;
+
+          case PT_WORD:
+          for (i = 1; i <= min; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_L || prop_category == ucp_N ||
+                 c == CHAR_UNDERSCORE)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          break;
+
+          /* This should not occur */
+
           default:
           RRETURN(PCRE_ERROR_INTERNAL);
           }
@@ -3439,11 +3669,11 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINCTEST(c, eptr);
           prop_category = UCD_CATEGORY(c);
-          if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
+          if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH);
           while (eptr < md->end_subject)
             {
             int len = 1;
@@ -3470,9 +3700,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+          if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH);
           eptr++;
           while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
           }
@@ -3484,7 +3714,7 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           eptr++;
           while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
@@ -3492,7 +3722,7 @@ for (;;)
         break;
 
         case OP_ANYBYTE:
-        if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH);
+        if (eptr > md->end_subject - min) MRRETURN(MATCH_NOMATCH);
         eptr += min;
         break;
 
@@ -3502,12 +3732,12 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           switch(c)
             {
-            default: RRETURN(MATCH_NOMATCH);
+            default: MRRETURN(MATCH_NOMATCH);
             case 0x000d:
             if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
             break;
@@ -3520,7 +3750,7 @@ for (;;)
             case 0x0085:
             case 0x2028:
             case 0x2029:
-            if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+            if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
             break;
             }
           }
@@ -3532,7 +3762,7 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           switch(c)
@@ -3557,7 +3787,7 @@ for (;;)
             case 0x202f:    /* NARROW NO-BREAK SPACE */
             case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
             case 0x3000:    /* IDEOGRAPHIC SPACE */
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           }
         break;
@@ -3568,12 +3798,12 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           switch(c)
             {
-            default: RRETURN(MATCH_NOMATCH);
+            default: MRRETURN(MATCH_NOMATCH);
             case 0x09:      /* HT */
             case 0x20:      /* SPACE */
             case 0xa0:      /* NBSP */
@@ -3604,7 +3834,7 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           switch(c)
@@ -3617,7 +3847,7 @@ for (;;)
             case 0x85:      /* NEL */
             case 0x2028:    /* LINE SEPARATOR */
             case 0x2029:    /* PARAGRAPH SEPARATOR */
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           }
         break;
@@ -3628,12 +3858,12 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           switch(c)
             {
-            default: RRETURN(MATCH_NOMATCH);
+            default: MRRETURN(MATCH_NOMATCH);
             case 0x0a:      /* LF */
             case 0x0b:      /* VT */
             case 0x0c:      /* FF */
@@ -3652,11 +3882,11 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINC(c, eptr);
           if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3666,10 +3896,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           /* No need to skip more bytes - we know it's a 1-byte character */
           }
         break;
@@ -3680,10 +3910,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
           }
         break;
@@ -3694,10 +3924,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           /* No need to skip more bytes - we know it's a 1-byte character */
           }
         break;
@@ -3708,10 +3938,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
           }
         break;
@@ -3722,10 +3952,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           /* No need to skip more bytes - we know it's a 1-byte character */
           }
         break;
@@ -3748,9 +3978,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+          if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH);
           eptr++;
           }
         break;
@@ -3759,7 +3989,7 @@ for (;;)
         if (eptr > md->end_subject - min)
           {
           SCHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
         eptr += min;
         break;
@@ -3768,7 +3998,7 @@ for (;;)
         if (eptr > md->end_subject - min)
           {
           SCHECK_PARTIAL();
-          RRETURN(MATCH_NOMATCH);
+          MRRETURN(MATCH_NOMATCH);
           }
         eptr += min;
         break;
@@ -3779,11 +4009,11 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           switch(*eptr++)
             {
-            default: RRETURN(MATCH_NOMATCH);
+            default: MRRETURN(MATCH_NOMATCH);
             case 0x000d:
             if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
             break;
@@ -3793,7 +4023,7 @@ for (;;)
             case 0x000b:
             case 0x000c:
             case 0x0085:
-            if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+            if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
             break;
             }
           }
@@ -3805,7 +4035,7 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           switch(*eptr++)
             {
@@ -3813,7 +4043,7 @@ for (;;)
             case 0x09:      /* HT */
             case 0x20:      /* SPACE */
             case 0xa0:      /* NBSP */
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           }
         break;
@@ -3824,11 +4054,11 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           switch(*eptr++)
             {
-            default: RRETURN(MATCH_NOMATCH);
+            default: MRRETURN(MATCH_NOMATCH);
             case 0x09:      /* HT */
             case 0x20:      /* SPACE */
             case 0xa0:      /* NBSP */
@@ -3843,7 +4073,7 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           switch(*eptr++)
             {
@@ -3853,7 +4083,7 @@ for (;;)
             case 0x0c:      /* FF */
             case 0x0d:      /* CR */
             case 0x85:      /* NEL */
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           }
         break;
@@ -3864,11 +4094,11 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           switch(*eptr++)
             {
-            default: RRETURN(MATCH_NOMATCH);
+            default: MRRETURN(MATCH_NOMATCH);
             case 0x0a:      /* LF */
             case 0x0b:      /* VT */
             case 0x0c:      /* FF */
@@ -3885,9 +4115,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
+          if ((md->ctypes[*eptr++] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3897,9 +4127,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
+          if ((md->ctypes[*eptr++] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3909,9 +4139,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
+          if ((md->ctypes[*eptr++] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3921,9 +4151,9 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
-          if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
+          if ((md->ctypes[*eptr++] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3933,10 +4163,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if ((md->ctypes[*eptr++] & ctype_word) != 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3946,10 +4176,10 @@ for (;;)
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if ((md->ctypes[*eptr++] & ctype_word) == 0)
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           }
         break;
 
@@ -3978,14 +4208,14 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            GETCHARINC(c, eptr);
-            if (prop_fail_result) RRETURN(MATCH_NOMATCH);
+            GETCHARINCTEST(c, eptr);
+            if (prop_fail_result) MRRETURN(MATCH_NOMATCH);
             }
           /* Control never gets here */
 
@@ -3994,18 +4224,18 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            GETCHARINC(c, eptr);
+            GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == ucp_Lu ||
                  prop_chartype == ucp_Ll ||
                  prop_chartype == ucp_Lt) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           /* Control never gets here */
 
@@ -4014,16 +4244,16 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            GETCHARINC(c, eptr);
+            GETCHARINCTEST(c, eptr);
             prop_category = UCD_CATEGORY(c);
             if ((prop_category == prop_value) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           /* Control never gets here */
 
@@ -4032,16 +4262,16 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            GETCHARINC(c, eptr);
+            GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == prop_value) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             }
           /* Control never gets here */
 
@@ -4050,19 +4280,101 @@ for (;;)
             {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-            if (fi >= max) RRETURN(MATCH_NOMATCH);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
-            GETCHARINC(c, eptr);
+            GETCHARINCTEST(c, eptr);
             prop_script = UCD_SCRIPT(c);
             if ((prop_script == prop_value) == prop_fail_result)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
+            }
+          /* Control never gets here */
+
+          case PT_ALNUM:
+          for (fi = min;; fi++)
+            {
+            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM59);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_L || prop_category == ucp_N)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          /* Control never gets here */
+
+          case PT_SPACE:    /* Perl space */
+          for (fi = min;; fi++)
+            {
+            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM60);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
             }
           /* Control never gets here */
 
+          case PT_PXSPACE:  /* POSIX space */
+          for (fi = min;; fi++)
+            {
+            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM61);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          /* Control never gets here */
+
+          case PT_WORD:
+          for (fi = min;; fi++)
+            {
+            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM62);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            if (fi >= max) MRRETURN(MATCH_NOMATCH);
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              MRRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_L ||
+                 prop_category == ucp_N ||
+                 c == CHAR_UNDERSCORE)
+                   == prop_fail_result)
+              MRRETURN(MATCH_NOMATCH);
+            }
+          /* Control never gets here */
+
+          /* This should never occur */
+
           default:
           RRETURN(PCRE_ERROR_INTERNAL);
           }
@@ -4077,15 +4389,15 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINCTEST(c, eptr);
           prop_category = UCD_CATEGORY(c);
-          if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
+          if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH);
           while (eptr < md->end_subject)
             {
             int len = 1;
@@ -4109,14 +4421,14 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (ctype == OP_ANY && IS_NEWLINE(eptr))
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           GETCHARINC(c, eptr);
           switch(ctype)
             {
@@ -4128,7 +4440,7 @@ for (;;)
             case OP_ANYNL:
             switch(c)
               {
-              default: RRETURN(MATCH_NOMATCH);
+              default: MRRETURN(MATCH_NOMATCH);
               case 0x000d:
               if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
               break;
@@ -4140,7 +4452,7 @@ for (;;)
               case 0x0085:
               case 0x2028:
               case 0x2029:
-              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+              if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
               break;
               }
             break;
@@ -4168,14 +4480,14 @@ for (;;)
               case 0x202f:    /* NARROW NO-BREAK SPACE */
               case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
               case 0x3000:    /* IDEOGRAPHIC SPACE */
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             break;
 
             case OP_HSPACE:
             switch(c)
               {
-              default: RRETURN(MATCH_NOMATCH);
+              default: MRRETURN(MATCH_NOMATCH);
               case 0x09:      /* HT */
               case 0x20:      /* SPACE */
               case 0xa0:      /* NBSP */
@@ -4210,14 +4522,14 @@ for (;;)
               case 0x85:      /* NEL */
               case 0x2028:    /* LINE SEPARATOR */
               case 0x2029:    /* PARAGRAPH SEPARATOR */
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             break;
 
             case OP_VSPACE:
             switch(c)
               {
-              default: RRETURN(MATCH_NOMATCH);
+              default: MRRETURN(MATCH_NOMATCH);
               case 0x0a:      /* LF */
               case 0x0b:      /* VT */
               case 0x0c:      /* FF */
@@ -4231,32 +4543,32 @@ for (;;)
 
             case OP_NOT_DIGIT:
             if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_DIGIT:
             if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_NOT_WHITESPACE:
             if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_WHITESPACE:
             if  (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_NOT_WORDCHAR:
             if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_WORDCHAR:
             if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
             break;
 
             default:
@@ -4272,14 +4584,14 @@ for (;;)
           {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-          if (fi >= max) RRETURN(MATCH_NOMATCH);
+          if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
             }
           if (ctype == OP_ANY && IS_NEWLINE(eptr))
-            RRETURN(MATCH_NOMATCH);
+            MRRETURN(MATCH_NOMATCH);
           c = *eptr++;
           switch(ctype)
             {
@@ -4291,7 +4603,7 @@ for (;;)
             case OP_ANYNL:
             switch(c)
               {
-              default: RRETURN(MATCH_NOMATCH);
+              default: MRRETURN(MATCH_NOMATCH);
               case 0x000d:
               if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
               break;
@@ -4302,7 +4614,7 @@ for (;;)
               case 0x000b:
               case 0x000c:
               case 0x0085:
-              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+              if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
               break;
               }
             break;
@@ -4314,14 +4626,14 @@ for (;;)
               case 0x09:      /* HT */
               case 0x20:      /* SPACE */
               case 0xa0:      /* NBSP */
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             break;
 
             case OP_HSPACE:
             switch(c)
               {
-              default: RRETURN(MATCH_NOMATCH);
+              default: MRRETURN(MATCH_NOMATCH);
               case 0x09:      /* HT */
               case 0x20:      /* SPACE */
               case 0xa0:      /* NBSP */
@@ -4338,14 +4650,14 @@ for (;;)
               case 0x0c:      /* FF */
               case 0x0d:      /* CR */
               case 0x85:      /* NEL */
-              RRETURN(MATCH_NOMATCH);
+              MRRETURN(MATCH_NOMATCH);
               }
             break;
 
             case OP_VSPACE:
             switch(c)
               {
-              default: RRETURN(MATCH_NOMATCH);
+              default: MRRETURN(MATCH_NOMATCH);
               case 0x0a:      /* LF */
               case 0x0b:      /* VT */
               case 0x0c:      /* FF */
@@ -4356,27 +4668,27 @@ for (;;)
             break;
 
             case OP_NOT_DIGIT:
-            if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
+            if ((md->ctypes[c] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_DIGIT:
-            if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
+            if ((md->ctypes[c] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_NOT_WHITESPACE:
-            if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
+            if ((md->ctypes[c] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_WHITESPACE:
-            if  ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
+            if  ((md->ctypes[c] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_NOT_WORDCHAR:
-            if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);
+            if ((md->ctypes[c] & ctype_word) != 0) MRRETURN(MATCH_NOMATCH);
             break;
 
             case OP_WORDCHAR:
-            if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);
+            if ((md->ctypes[c] & ctype_word) == 0) MRRETURN(MATCH_NOMATCH);
             break;
 
             default:
@@ -4409,7 +4721,7 @@ for (;;)
               SCHECK_PARTIAL();
               break;
               }
-            GETCHARLEN(c, eptr, len);
+            GETCHARLENTEST(c, eptr, len);
             if (prop_fail_result) break;
             eptr+= len;
             }
@@ -4424,7 +4736,7 @@ for (;;)
               SCHECK_PARTIAL();
               break;
               }
-            GETCHARLEN(c, eptr, len);
+            GETCHARLENTEST(c, eptr, len);
             prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == ucp_Lu ||
                  prop_chartype == ucp_Ll ||
@@ -4443,7 +4755,7 @@ for (;;)
               SCHECK_PARTIAL();
               break;
               }
-            GETCHARLEN(c, eptr, len);
+            GETCHARLENTEST(c, eptr, len);
             prop_category = UCD_CATEGORY(c);
             if ((prop_category == prop_value) == prop_fail_result)
               break;
@@ -4460,7 +4772,7 @@ for (;;)
               SCHECK_PARTIAL();
               break;
               }
-            GETCHARLEN(c, eptr, len);
+            GETCHARLENTEST(c, eptr, len);
             prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == prop_value) == prop_fail_result)
               break;
@@ -4477,13 +4789,90 @@ for (;;)
               SCHECK_PARTIAL();
               break;
               }
-            GETCHARLEN(c, eptr, len);
+            GETCHARLENTEST(c, eptr, len);
             prop_script = UCD_SCRIPT(c);
             if ((prop_script == prop_value) == prop_fail_result)
               break;
             eptr+= len;
             }
           break;
+
+          case PT_ALNUM:
+          for (i = min; i < max; i++)
+            {
+            int len = 1;
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            GETCHARLENTEST(c, eptr, len);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_L || prop_category == ucp_N)
+                 == prop_fail_result)
+              break;
+            eptr+= len;
+            }
+          break;
+
+          case PT_SPACE:    /* Perl space */
+          for (i = min; i < max; i++)
+            {
+            int len = 1;
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            GETCHARLENTEST(c, eptr, len);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_FF || c == CHAR_CR)
+                 == prop_fail_result)
+              break;
+            eptr+= len;
+            }
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          for (i = min; i < max; i++)
+            {
+            int len = 1;
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            GETCHARLENTEST(c, eptr, len);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
+                 == prop_fail_result)
+              break;
+            eptr+= len;
+            }
+          break;
+
+          case PT_WORD:
+          for (i = min; i < max; i++)
+            {
+            int len = 1;
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            GETCHARLENTEST(c, eptr, len);
+            prop_category = UCD_CATEGORY(c);
+            if ((prop_category == ucp_L || prop_category == ucp_N ||
+                 c == CHAR_UNDERSCORE) == prop_fail_result)
+              break;
+            eptr+= len;
+            }
+          break;
+
+          default:
+          RRETURN(PCRE_ERROR_INTERNAL);
           }
 
         /* eptr is now past the end of the maximum run */
@@ -5036,7 +5425,7 @@ for (;;)
 
       /* Get here if we can't make it match with any permitted repetitions */
 
-      RRETURN(MATCH_NOMATCH);
+      MRRETURN(MATCH_NOMATCH);
       }
     /* Control never gets here */
 
@@ -5069,12 +5458,13 @@ switch (frame->Xwhere)
   LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)
   LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)
   LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)
-  LBL(53) LBL(54)
+  LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58)
 #ifdef SUPPORT_UTF8
   LBL(16) LBL(18) LBL(20) LBL(21) LBL(22) LBL(23) LBL(28) LBL(30)
   LBL(32) LBL(34) LBL(42) LBL(46)
 #ifdef SUPPORT_UCP
   LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)
+  LBL(59) LBL(60) LBL(61) LBL(62)
 #endif  /* SUPPORT_UCP */
 #endif  /* SUPPORT_UTF8 */
   default:
@@ -5278,6 +5668,7 @@ end_subject = md->end_subject;
 
 md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
 utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0;
+md->use_ucp = (re->options & PCRE_UCP) != 0;
 md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
 
 md->notbol = (options & PCRE_NOTBOL) != 0;
@@ -5287,6 +5678,7 @@ md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
 md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 :
               ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0;
 md->hitend = FALSE;
+md->mark = NULL;                        /* In case never set */
 
 md->recursive = NULL;                   /* No recursion at top level */
 
@@ -5565,8 +5957,16 @@ for(;;)
       while (start_match < end_subject)
         {
         register unsigned int c = *start_match;
-        if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++;
-          else break;
+        if ((start_bits[c/8] & (1 << (c&7))) == 0)
+          {
+          start_match++;
+#ifdef SUPPORT_UTF8
+          if (utf8)
+            while(start_match < end_subject && (*start_match & 0xc0) == 0x80)
+              start_match++;
+#endif
+          }
+        else break;
         }
       }
     }   /* Starting optimizations */
@@ -5667,6 +6067,23 @@ for(;;)
 
   switch(rc)
     {
+    /* SKIP passes back the next starting point explicitly, but if it is the
+    same as the match we have just done, treat it as NOMATCH. */
+
+    case MATCH_SKIP:
+    if (md->start_match_ptr != start_match)
+      {
+      new_start_match = md->start_match_ptr;
+      break;
+      }
+    /* Fall through */
+
+    /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched
+    the SKIP's arg was not found. We also treat this as NOMATCH. */
+
+    case MATCH_SKIP_ARG:
+    /* Fall through */
+
     /* NOMATCH and PRUNE advance by one character. THEN at this level acts
     exactly like PRUNE. */
 
@@ -5681,12 +6098,6 @@ for(;;)
 #endif
     break;
 
-    /* SKIP passes back the next starting point explicitly. */
-
-    case MATCH_SKIP:
-    new_start_match = md->start_match_ptr;
-    break;
-
     /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */
 
     case MATCH_COMMIT:
@@ -5732,7 +6143,8 @@ for(;;)
          md->nllen == 2))
     start_match++;
 
-  }   /* End of for(;;) "bumpalong" loop */
+  md->mark = NULL;   /* Reset for start of next match attempt */
+  }                  /* End of for(;;) "bumpalong" loop */
 
 /* ==========================================================================*/
 
@@ -5756,7 +6168,7 @@ capturing parentheses than vector slots. */
 
 ENDLOOP:
 
-if (rc == MATCH_MATCH)
+if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
   {
   if (using_temporary_offsets)
     {
@@ -5782,12 +6194,12 @@ if (rc == MATCH_MATCH)
 
   if (offsetcount < 2) rc = 0; else
     {
-    offsets[0] = md->start_match_ptr - md->start_subject;
-    offsets[1] = md->end_match_ptr - md->start_subject;
+    offsets[0] = (int)(md->start_match_ptr - md->start_subject);
+    offsets[1] = (int)(md->end_match_ptr - md->start_subject);
     }
 
   DPRINTF((">>>> returning %d\n", rc));
-  return rc;
+  goto RETURN_MARK;
   }
 
 /* Control gets here if there has been an error, or if the overall match
@@ -5799,26 +6211,43 @@ if (using_temporary_offsets)
   (pcre_free)(md->offset_vector);
   }
 
+/* For anything other than nomatch or partial match, just return the code. */
+
 if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
   {
   DPRINTF((">>>> error: returning %d\n", rc));
   return rc;
   }
-else if (start_partial != NULL)
+
+/* Handle partial matches - disable any mark data */
+
+if (start_partial != NULL)
   {
   DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
+  md->mark = NULL;
   if (offsetcount > 1)
     {
-    offsets[0] = start_partial - (USPTR)subject;
-    offsets[1] = end_subject - (USPTR)subject;
+    offsets[0] = (int)(start_partial - (USPTR)subject);
+    offsets[1] = (int)(end_subject - (USPTR)subject);
     }
-  return PCRE_ERROR_PARTIAL;
+  rc = PCRE_ERROR_PARTIAL;
   }
+
+/* This is the classic nomatch case */
+
 else
   {
   DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
-  return PCRE_ERROR_NOMATCH;
+  rc = PCRE_ERROR_NOMATCH;
   }
+
+/* Return the MARK data if it has been requested. */
+
+RETURN_MARK:
+
+if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
+  *(extra_data->mark) = (unsigned char *)(md->mark);
+return rc;
 }
 
 /* End of pcre_exec.c */
index 0938782a78af8af592406b130d9bb01061585ccc..e293602fe6a37722ac04048494d87805b9dc5361 100644 (file)
@@ -191,9 +191,8 @@ arithmetic. Handle this by defining a macro for the appropriate type. If
 stdint.h is available, include it; it may define INT64_MAX. Systems that do not
 have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set
 by "configure". */
-#ifdef PHP_WIN32
-#include "win32/php_stdint.h"
-#elif HAVE_STDINT_H
+
+#if HAVE_STDINT_H
 #include <stdint.h>
 #elif HAVE_INTTYPES_H
 #include <inttypes.h>
@@ -476,7 +475,8 @@ know we are in UTF-8 mode. */
       } \
     }
 
-/* Get the next character, testing for UTF-8 mode, and advancing the pointer */
+/* Get the next character, testing for UTF-8 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-8 mode. */
 
 #define GETCHARINCTEST(c, eptr) \
   c = *eptr++; \
@@ -513,7 +513,7 @@ if there are extra bytes. This is called when we know we are in UTF-8 mode. */
 
 /* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the
 pointer, incrementing length if there are extra bytes. This is called when we
-know we are in UTF-8 mode. */
+do not know if we are in UTF-8 mode. */
 
 #define GETCHARLENTEST(c, eptr, len) \
   c = *eptr; \
@@ -581,7 +581,7 @@ time, run time, or study time, respectively. */
    PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \
    PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \
    PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \
-   PCRE_JAVASCRIPT_COMPAT)
+   PCRE_JAVASCRIPT_COMPAT|PCRE_UCP)
 
 #define PUBLIC_EXEC_OPTIONS \
   (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \
@@ -876,6 +876,7 @@ so that PCRE works on both ASCII and EBCDIC platforms, in non-UTF-mode only. */
 #define STRING_COMMIT0              "COMMIT\0"
 #define STRING_F0                   "F\0"
 #define STRING_FAIL0                "FAIL\0"
+#define STRING_MARK0                "MARK\0"
 #define STRING_PRUNE0               "PRUNE\0"
 #define STRING_SKIP0                "SKIP\0"
 #define STRING_THEN                 "THEN"
@@ -905,6 +906,7 @@ so that PCRE works on both ASCII and EBCDIC platforms, in non-UTF-mode only. */
 #define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)"
 #define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)"
 #define STRING_UTF8_RIGHTPAR        "UTF8)"
+#define STRING_UCP_RIGHTPAR         "UCP)"
 
 #else  /* SUPPORT_UTF8 */
 
@@ -1128,6 +1130,7 @@ only. */
 #define STRING_COMMIT0              STR_C STR_O STR_M STR_M STR_I STR_T "\0"
 #define STRING_F0                   STR_F "\0"
 #define STRING_FAIL0                STR_F STR_A STR_I STR_L "\0"
+#define STRING_MARK0                STR_M STR_A STR_R STR_K "\0"
 #define STRING_PRUNE0               STR_P STR_R STR_U STR_N STR_E "\0"
 #define STRING_SKIP0                STR_S STR_K STR_I STR_P "\0"
 #define STRING_THEN                 STR_T STR_H STR_E STR_N
@@ -1157,6 +1160,7 @@ only. */
 #define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
 #define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS
 #define STRING_UTF8_RIGHTPAR        STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS
+#define STRING_UCP_RIGHTPAR         STR_U STR_C STR_P STR_RIGHT_PARENTHESIS
 
 #endif  /* SUPPORT_UTF8 */
 
@@ -1189,9 +1193,13 @@ only. */
 
 #define PT_ANY        0    /* Any property - matches all chars */
 #define PT_LAMP       1    /* L& - the union of Lu, Ll, Lt */
-#define PT_GC         2    /* General characteristic (e.g. L) */
-#define PT_PC         3    /* Particular characteristic (e.g. Lu) */
+#define PT_GC         2    /* Specified general characteristic (e.g. L) */
+#define PT_PC         3    /* Specified particular characteristic (e.g. Lu) */
 #define PT_SC         4    /* Script (e.g. Han) */
+#define PT_ALNUM      5    /* Alphanumeric - the union of L and N */
+#define PT_SPACE      6    /* Perl space - Z plus 9,10,12,13 */
+#define PT_PXSPACE    7    /* POSIX space - Z plus 9,10,11,12,13 */
+#define PT_WORD       8    /* Word - L plus N plus underscore */
 
 /* Flag bits and data types for the extended class (OP_XCLASS) for classes that
 contain UTF-8 characters with values greater than 255. */
@@ -1208,9 +1216,15 @@ contain UTF-8 characters with values greater than 255. */
 /* These are escaped items that aren't just an encoding of a particular data
 value such as \n. They must have non-zero values, as check_escape() returns
 their negation. Also, they must appear in the same order as in the opcode
-definitions below, up to ESC_z. There's a dummy for OP_ANY because it
-corresponds to "." rather than an escape sequence, and another for OP_ALLANY
-(which is used for [^] in JavaScript compatibility mode).
+definitions below, up to ESC_z. There's a dummy for OP_ALLANY because it
+corresponds to "." in DOTALL mode rather than an escape sequence. It is also
+used for [^] in JavaScript compatibility mode. In non-DOTALL mode, "." behaves
+like \N.
+
+The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc.
+when PCRE_UCP is set, when replacement of \d etc by \p sequences is required.
+They must be contiguous, and remain in order so that the replacements can be
+looked up from a table.
 
 The final escape must be ESC_REF as subsequent values are used for
 backreferences (\1, \2, \3, etc). There are two tests in the code for an escape
@@ -1220,11 +1234,12 @@ put in between that don't consume a character, that code will have to change.
 */
 
 enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
-       ESC_W, ESC_w, ESC_dum1, ESC_dum2, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,
-       ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z, ESC_E, ESC_Q, ESC_g, ESC_k,
+       ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,
+       ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z,
+       ESC_E, ESC_Q, ESC_g, ESC_k,
+       ESC_DU, ESC_du, ESC_SU, ESC_su, ESC_WU, ESC_wu,
        ESC_REF };
 
-
 /* Opcode table: Starting from 1 (i.e. after OP_END), the values up to
 OP_EOD must correspond in order to the list of escapes immediately above.
 
@@ -1248,8 +1263,8 @@ enum {
   OP_WHITESPACE,         /*  9 \s */
   OP_NOT_WORDCHAR,       /* 10 \W */
   OP_WORDCHAR,           /* 11 \w */
-  OP_ANY,            /* 12 Match any character (subject to DOTALL) */
-  OP_ALLANY,         /* 13 Match any character (not subject to DOTALL) */
+  OP_ANY,            /* 12 Match any character except newline */
+  OP_ALLANY,         /* 13 Match any character */
   OP_ANYBYTE,        /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */
   OP_NOTPROP,        /* 15 \P (not Unicode property) */
   OP_PROP,           /* 16 \p (Unicode property) */
@@ -1379,20 +1394,24 @@ enum {
 
   /* These are backtracking control verbs */
 
-  OP_PRUNE,          /* 107 */
-  OP_SKIP,           /* 108 */
-  OP_THEN,           /* 109 */
-  OP_COMMIT,         /* 110 */
+  OP_MARK,           /* 107 always has an argument */
+  OP_PRUNE,          /* 108 */
+  OP_PRUNE_ARG,      /* 109 same, but with argument */
+  OP_SKIP,           /* 110 */
+  OP_SKIP_ARG,       /* 111 same, but with argument */
+  OP_THEN,           /* 112 */
+  OP_THEN_ARG,       /* 113 same, but with argument */
+  OP_COMMIT,         /* 114 */
 
   /* These are forced failure and success verbs */
 
-  OP_FAIL,           /* 111 */
-  OP_ACCEPT,         /* 112 */
-  OP_CLOSE,          /* 113 Used before OP_ACCEPT to close open captures */
+  OP_FAIL,           /* 115 */
+  OP_ACCEPT,         /* 116 */
+  OP_CLOSE,          /* 117 Used before OP_ACCEPT to close open captures */
 
   /* This is used to skip a subpattern with a {0} quantifier */
 
-  OP_SKIPZERO,       /* 114 */
+  OP_SKIPZERO,       /* 118 */
 
   /* This is not an opcode, but is used to check that tables indexed by opcode
   are the correct length, in order to catch updating errors - there have been
@@ -1403,7 +1422,7 @@ enum {
 
 /* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro
 definitions that follow must also be updated to match. There are also tables
-called "coptable" cna "poptable" in pcre_dfa_exec.c that must be updated. */
+called "coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */
 
 
 /* This macro defines textual names for all the opcodes. These are used only
@@ -1428,7 +1447,8 @@ for debugging. The macro is referenced only in pcre_printint.c. */
   "Once", "Bra", "CBra", "Cond", "SBra", "SCBra", "SCond",        \
   "Cond ref", "Cond nref", "Cond rec", "Cond nrec", "Cond def",   \
   "Brazero", "Braminzero",                                        \
-  "*PRUNE", "*SKIP", "*THEN", "*COMMIT", "*FAIL", "*ACCEPT",      \
+  "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP",                  \
+  "*THEN", "*THEN", "*COMMIT", "*FAIL", "*ACCEPT",                \
   "Close", "Skip zero"
 
 
@@ -1494,8 +1514,9 @@ in UTF-8 mode. The code that uses this table must know about such things. */
   3, 3,                          /* RREF, NRREF                            */ \
   1,                             /* DEF                                    */ \
   1, 1,                          /* BRAZERO, BRAMINZERO                    */ \
-  1, 1, 1, 1,                    /* PRUNE, SKIP, THEN, COMMIT,             */ \
-  1, 1, 3, 1                     /* FAIL, ACCEPT, CLOSE, SKIPZERO          */
+  3, 1, 3,                       /* MARK, PRUNE, PRUNE_ARG,                */ \
+  1, 3, 1, 3,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */ \
+  1, 1, 1, 3, 1                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */
 
 
 /* A magic value for OP_RREF and OP_NRREF to indicate the "any recursion"
@@ -1513,7 +1534,7 @@ enum { ERR0,  ERR1,  ERR2,  ERR3,  ERR4,  ERR5,  ERR6,  ERR7,  ERR8,  ERR9,
        ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39,
        ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49,
        ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
-       ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERRCOUNT };
+       ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERRCOUNT };
 
 /* The real format of the start of the pcre block; the index of names and the
 code vector run on as long as necessary after the end. We store an explicit
@@ -1656,6 +1677,7 @@ typedef struct match_data {
   BOOL   noteol;                /* NOTEOL flag */
   BOOL   utf8;                  /* UTF8 flag */
   BOOL   jscript_compat;        /* JAVASCRIPT_COMPAT flag */
+  BOOL   use_ucp;               /* PCRE_UCP flag */
   BOOL   endonly;               /* Dollar not before final \n */
   BOOL   notempty;              /* Empty string match not wanted */
   BOOL   notempty_atstart;      /* Empty string match at start not wanted */
@@ -1675,6 +1697,7 @@ typedef struct match_data {
   int    eptrn;                 /* Next free eptrblock */
   recursion_info *recursive;    /* Linked list of recursion data */
   void  *callout_data;          /* To pass back to callouts */
+  const uschar *mark;           /* Mark pointer to pass back */
 } match_data;
 
 /* A similar structure is used for the same purpose by the DFA matching
index 86b02b5ca4231708ae8a1e0f3a05703cb177bc36..49d93174ccec3f128bd93ec3e0df2817bd2a8b7c 100644 (file)
@@ -534,6 +534,14 @@ for(;;)
       }
     break;
 
+    case OP_MARK:
+    case OP_PRUNE_ARG:
+    case OP_SKIP_ARG:
+    case OP_THEN_ARG:
+    fprintf(f, "    %s %s", OP_names[*code], code + 2);
+    extra += code[1];
+    break;
+
     /* Anything else is just an item with no data*/
 
     default:
index 2653624e0a4d3095497f97ff2f243622268ac898..3ac7e8149684296a561f64dde59a12a891dae720 100644 (file)
@@ -46,6 +46,7 @@ supporting functions. */
 
 #include "pcre_internal.h"
 
+#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7))
 
 /* Returns from set_start_bits() */
 
@@ -411,6 +412,15 @@ for (;;)
 #endif
     break;
 
+    /* Skip these, but we need to add in the name length. */
+
+    case OP_MARK:
+    case OP_PRUNE_ARG:
+    case OP_SKIP_ARG:
+    case OP_THEN_ARG:
+    cc += _pcre_OP_lengths[op] + cc[1];
+    break;
+
     /* For the record, these are the opcodes that are matched by "default":
     OP_ACCEPT, OP_CLOSE, OP_COMMIT, OP_FAIL, OP_PRUNE, OP_SET_SOM, OP_SKIP,
     OP_THEN. */
@@ -429,25 +439,121 @@ for (;;)
 *      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.
+/* Given a character, set its first byte's bit in the table, and also the
+corresponding bit for the other version of a letter if we are caseless. In
+UTF-8 mode, for characters greater than 127, we can only do the caseless thing
+when Unicode property support is available.
 
 Arguments:
   start_bits    points to the bit map
-  c             is the character
+  p             points to the character
   caseless      the caseless flag
   cd            the block with char table pointers
+  utf8          TRUE for UTF-8 mode
+
+Returns:        pointer after the character
+*/
+
+static const uschar *
+set_table_bit(uschar *start_bits, const uschar *p, BOOL caseless,
+  compile_data *cd, BOOL utf8)
+{
+unsigned int c = *p;
+
+SET_BIT(c);
+
+#ifdef SUPPORT_UTF8
+if (utf8 && c > 127)
+  {
+  GETCHARINC(c, p);
+#ifdef SUPPORT_UCP
+  if (caseless)
+    {
+    uschar buff[8];
+    c = UCD_OTHERCASE(c);
+    (void)_pcre_ord2utf8(c, buff);
+    SET_BIT(buff[0]);
+    }
+#endif
+  return p;
+  }
+#endif
+
+/* Not UTF-8 mode, or character is less than 127. */
+
+if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
+return p + 1;
+}
+
+
 
-Returns:        nothing
+/*************************************************
+*     Set bits for a positive character type     *
+*************************************************/
+
+/* This function sets starting bits for a character type. In UTF-8 mode, we can
+only do a direct setting for bytes less than 128, as otherwise there can be
+confusion with bytes in the middle of UTF-8 characters. In a "traditional"
+environment, the tables will only recognize ASCII characters anyway, but in at
+least one Windows environment, some higher bytes bits were set in the tables.
+So we deal with that case by considering the UTF-8 encoding.
+
+Arguments:
+  start_bits     the starting bitmap
+  cbit type      the type of character wanted
+  table_limit    32 for non-UTF-8; 16 for UTF-8
+  cd             the block with char table pointers
+
+Returns:         nothing
 */
 
 static void
-set_table_bit(uschar *start_bits, unsigned int c, BOOL caseless,
+set_type_bits(uschar *start_bits, int cbit_type, int table_limit,
   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));
+register int c;
+for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type];
+if (table_limit == 32) return;
+for (c = 128; c < 256; c++)
+  {
+  if ((cd->cbits[c/8] & (1 << (c&7))) != 0)
+    {
+    uschar buff[8];
+    (void)_pcre_ord2utf8(c, buff);
+    SET_BIT(buff[0]);
+    }
+  }
+}
+
+
+/*************************************************
+*     Set bits for a negative character type     *
+*************************************************/
+
+/* This function sets starting bits for a negative character type such as \D.
+In UTF-8 mode, we can only do a direct setting for bytes less than 128, as
+otherwise there can be confusion with bytes in the middle of UTF-8 characters.
+Unlike in the positive case, where we can set appropriate starting bits for
+specific high-valued UTF-8 characters, in this case we have to set the bits for
+all high-valued characters. The lowest is 0xc2, but we overkill by starting at
+0xc0 (192) for simplicity.
+
+Arguments:
+  start_bits     the starting bitmap
+  cbit type      the type of character wanted
+  table_limit    32 for non-UTF-8; 16 for UTF-8
+  cd             the block with char table pointers
+
+Returns:         nothing
+*/
+
+static void
+set_nottype_bits(uschar *start_bits, int cbit_type, int table_limit,
+  compile_data *cd)
+{
+register int c;
+for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type];
+if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff;
 }
 
 
@@ -482,6 +588,7 @@ set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless,
 {
 register int c;
 int yield = SSB_DONE;
+int table_limit = utf8? 16:32;
 
 #if 0
 /* ========================================================================= */
@@ -605,12 +712,7 @@ do
       case OP_QUERY:
       case OP_MINQUERY:
       case OP_POSQUERY:
-      set_table_bit(start_bits, tcode[1], caseless, cd);
-      tcode += 2;
-#ifdef SUPPORT_UTF8
-      if (utf8 && tcode[-1] >= 0xc0)
-        tcode += _pcre_utf8_table4[tcode[-1] & 0x3f];
-#endif
+      tcode = set_table_bit(start_bits, tcode + 1, caseless, cd, utf8);
       break;
 
       /* Single-char upto sets the bit and tries the next */
@@ -618,12 +720,7 @@ do
       case OP_UPTO:
       case OP_MINUPTO:
       case OP_POSUPTO:
-      set_table_bit(start_bits, tcode[3], caseless, cd);
-      tcode += 4;
-#ifdef SUPPORT_UTF8
-      if (utf8 && tcode[-1] >= 0xc0)
-        tcode += _pcre_utf8_table4[tcode[-1] & 0x3f];
-#endif
+      tcode = set_table_bit(start_bits, tcode + 3, caseless, cd, utf8);
       break;
 
       /* At least one single char sets the bit and stops */
@@ -636,59 +733,86 @@ do
       case OP_PLUS:
       case OP_MINPLUS:
       case OP_POSPLUS:
-      set_table_bit(start_bits, tcode[1], caseless, cd);
+      (void)set_table_bit(start_bits, tcode + 1, caseless, cd, utf8);
       try_next = FALSE;
       break;
 
-      /* Single character type sets the bits and stops */
+      /* Special spacing and line-terminating items. These recognize specific
+      lists of characters. The difference between VSPACE and ANYNL is that the
+      latter can match the two-character CRLF sequence, but that is not
+      relevant for finding the first character, so their code here is
+      identical. */
+
+      case OP_HSPACE:
+      SET_BIT(0x09);
+      SET_BIT(0x20);
+      if (utf8)
+        {
+        SET_BIT(0xC2);  /* For U+00A0 */
+        SET_BIT(0xE1);  /* For U+1680, U+180E */
+        SET_BIT(0xE2);  /* For U+2000 - U+200A, U+202F, U+205F */
+        SET_BIT(0xE3);  /* For U+3000 */
+        }
+      else SET_BIT(0xA0);
+      try_next = FALSE;
+      break;
+
+      case OP_ANYNL:
+      case OP_VSPACE:
+      SET_BIT(0x0A);
+      SET_BIT(0x0B);
+      SET_BIT(0x0C);
+      SET_BIT(0x0D);
+      if (utf8)
+        {
+        SET_BIT(0xC2);  /* For U+0085 */
+        SET_BIT(0xE2);  /* For U+2028, U+2029 */
+        }
+      else SET_BIT(0x85);
+      try_next = FALSE;
+      break;
+
+      /* Single character types set the bits and stop. Note that if PCRE_UCP
+      is set, we do not see these op codes because \d etc are converted to
+      properties. Therefore, these apply in the case when only characters less
+      than 256 are recognized to match the types. */
 
       case OP_NOT_DIGIT:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= ~cd->cbits[c+cbit_digit];
+      set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
       try_next = FALSE;
       break;
 
       case OP_DIGIT:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= cd->cbits[c+cbit_digit];
+      set_type_bits(start_bits, cbit_digit, table_limit, cd);
       try_next = FALSE;
       break;
 
       /* The cbit_space table has vertical tab as whitespace; we have to
-      discard it. */
+      ensure it is set as not whitespace. */
 
       case OP_NOT_WHITESPACE:
-      for (c = 0; c < 32; c++)
-        {
-        int d = cd->cbits[c+cbit_space];
-        if (c == 1) d &= ~0x08;
-        start_bits[c] |= ~d;
-        }
+      set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+      start_bits[1] |= 0x08;
       try_next = FALSE;
       break;
 
       /* The cbit_space table has vertical tab as whitespace; we have to
-      discard it. */
+      not set it from the table. */
 
       case OP_WHITESPACE:
-      for (c = 0; c < 32; c++)
-        {
-        int d = cd->cbits[c+cbit_space];
-        if (c == 1) d &= ~0x08;
-        start_bits[c] |= d;
-        }
+      c = start_bits[1];    /* Save in case it was already set */
+      set_type_bits(start_bits, cbit_space, table_limit, cd);
+      start_bits[1] = (start_bits[1] & ~0x08) | c;
       try_next = FALSE;
       break;
 
       case OP_NOT_WORDCHAR:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= ~cd->cbits[c+cbit_word];
+      set_nottype_bits(start_bits, cbit_word, table_limit, cd);
       try_next = FALSE;
       break;
 
       case OP_WORDCHAR:
-      for (c = 0; c < 32; c++)
-        start_bits[c] |= cd->cbits[c+cbit_word];
+      set_type_bits(start_bits, cbit_word, table_limit, cd);
       try_next = FALSE;
       break;
 
@@ -697,6 +821,7 @@ do
 
       case OP_TYPEPLUS:
       case OP_TYPEMINPLUS:
+      case OP_TYPEPOSPLUS:
       tcode++;
       break;
 
@@ -720,52 +845,69 @@ do
       case OP_TYPEPOSQUERY:
       switch(tcode[1])
         {
+        default:
         case OP_ANY:
         case OP_ALLANY:
         return SSB_FAIL;
 
+        case OP_HSPACE:
+        SET_BIT(0x09);
+        SET_BIT(0x20);
+        if (utf8)
+          {
+          SET_BIT(0xC2);  /* For U+00A0 */
+          SET_BIT(0xE1);  /* For U+1680, U+180E */
+          SET_BIT(0xE2);  /* For U+2000 - U+200A, U+202F, U+205F */
+          SET_BIT(0xE3);  /* For U+3000 */
+          }
+        else SET_BIT(0xA0);
+        break;
+
+        case OP_ANYNL:
+        case OP_VSPACE:
+        SET_BIT(0x0A);
+        SET_BIT(0x0B);
+        SET_BIT(0x0C);
+        SET_BIT(0x0D);
+        if (utf8)
+          {
+          SET_BIT(0xC2);  /* For U+0085 */
+          SET_BIT(0xE2);  /* For U+2028, U+2029 */
+          }
+        else SET_BIT(0x85);
+        break;
+
         case OP_NOT_DIGIT:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= ~cd->cbits[c+cbit_digit];
+        set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
         break;
 
         case OP_DIGIT:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= cd->cbits[c+cbit_digit];
+        set_type_bits(start_bits, cbit_digit, table_limit, cd);
         break;
 
         /* The cbit_space table has vertical tab as whitespace; we have to
-        discard it. */
+        ensure it gets set as not whitespace. */
 
         case OP_NOT_WHITESPACE:
-        for (c = 0; c < 32; c++)
-          {
-          int d = cd->cbits[c+cbit_space];
-          if (c == 1) d &= ~0x08;
-          start_bits[c] |= ~d;
-          }
+        set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+        start_bits[1] |= 0x08;
         break;
 
         /* The cbit_space table has vertical tab as whitespace; we have to
-        discard it. */
+        avoid setting it. */
 
         case OP_WHITESPACE:
-        for (c = 0; c < 32; c++)
-          {
-          int d = cd->cbits[c+cbit_space];
-          if (c == 1) d &= ~0x08;
-          start_bits[c] |= d;
-          }
+        c = start_bits[1];    /* Save in case it was already set */
+        set_type_bits(start_bits, cbit_space, table_limit, cd);
+        start_bits[1] = (start_bits[1] & ~0x08) | c;
         break;
 
         case OP_NOT_WORDCHAR:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= ~cd->cbits[c+cbit_word];
+        set_nottype_bits(start_bits, cbit_word, table_limit, cd);
         break;
 
         case OP_WORDCHAR:
-        for (c = 0; c < 32; c++)
-          start_bits[c] |= cd->cbits[c+cbit_word];
+        set_type_bits(start_bits, cbit_word, table_limit, cd);
         break;
         }
 
index fbccd56857921e161ac11f811719793e215751cc..4dfcbc6f9db2bfebdab9f91870c7b99bb43b9f4f 100644 (file)
@@ -241,6 +241,10 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
 #define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"
 #define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
 #define STRING_Vai0 STR_V STR_a STR_i "\0"
+#define STRING_Xan0 STR_X STR_a STR_n "\0"
+#define STRING_Xps0 STR_X STR_p STR_s "\0"
+#define STRING_Xsp0 STR_X STR_s STR_p "\0"
+#define STRING_Xwd0 STR_X STR_w STR_d "\0"
 #define STRING_Yi0 STR_Y STR_i "\0"
 #define STRING_Z0 STR_Z "\0"
 #define STRING_Zl0 STR_Z STR_l "\0"
@@ -374,6 +378,10 @@ const char _pcre_utt_names[] =
   STRING_Tifinagh0
   STRING_Ugaritic0
   STRING_Vai0
+  STRING_Xan0
+  STRING_Xps0
+  STRING_Xsp0
+  STRING_Xwd0
   STRING_Yi0
   STRING_Z0
   STRING_Zl0
@@ -507,11 +515,15 @@ const ucp_type_table _pcre_utt[] = {
   { 891, PT_SC, ucp_Tifinagh },
   { 900, PT_SC, ucp_Ugaritic },
   { 909, PT_SC, ucp_Vai },
-  { 913, PT_SC, ucp_Yi },
-  { 916, PT_GC, ucp_Z },
-  { 918, PT_PC, ucp_Zl },
-  { 921, PT_PC, ucp_Zp },
-  { 924, PT_PC, ucp_Zs }
+  { 913, PT_ALNUM, 0 },
+  { 917, PT_PXSPACE, 0 },
+  { 921, PT_SPACE, 0 },
+  { 925, PT_WORD, 0 },
+  { 929, PT_SC, ucp_Yi },
+  { 932, PT_GC, ucp_Z },
+  { 934, PT_PC, ucp_Zl },
+  { 937, PT_PC, ucp_Zp },
+  { 940, PT_PC, ucp_Zs }
 };
 
 const int _pcre_utt_size = sizeof(_pcre_utt)/sizeof(ucp_type_table);
index 3fc3ba368aa4dcfad1867a4bcab61980cfe0f5c7..98841c5560c0d0224ac2d5964b99a902716a70f9 100644 (file)
@@ -6,7 +6,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2009 University of Cambridge
+           Copyright (c) 1997-2010 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -110,12 +110,13 @@ while ((t = *data++) != XCL_END)
       break;
 
       case PT_LAMP:
-      if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt) ==
-          (t == XCL_PROP)) return !negated;
+      if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+           prop->chartype == ucp_Lt) == (t == XCL_PROP)) return !negated;
       break;
 
       case PT_GC:
-      if ((data[1] == _pcre_ucp_gentype[prop->chartype]) == (t == XCL_PROP)) return !negated;
+      if ((data[1] == _pcre_ucp_gentype[prop->chartype]) == (t == XCL_PROP))
+        return !negated;
       break;
 
       case PT_PC:
@@ -126,6 +127,33 @@ while ((t = *data++) != XCL_END)
       if ((data[1] == prop->script) == (t == XCL_PROP)) return !negated;
       break;
 
+      case PT_ALNUM:
+      if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
+           _pcre_ucp_gentype[prop->chartype] == ucp_N) == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_SPACE:    /* Perl space */
+      if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
+           c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
+             == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_PXSPACE:  /* POSIX space */
+      if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
+           c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+           c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_WORD:
+      if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
+           _pcre_ucp_gentype[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
+             == (t == XCL_PROP))
+        return !negated;
+      break;
+
       /* This should never occur, but compilers may mutter if there is no
       default. */
 
index bae2054164826c1bdb7ea139198f8a68ec36ac0a..29d84468295f24faacfe4480a84d9852a85f6e8e 100644 (file)
@@ -6,7 +6,7 @@
 and semantics are as close as possible to those of the Perl 5 language.
 
                        Written by Philip Hazel
-           Copyright (c) 1997-2009 University of Cambridge
+           Copyright (c) 1997-2010 University of Cambridge
 
 -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,11 @@ previously been set. */
 #  define PCREPOSIX_EXP_DEFN __declspec(dllexport)
 #endif
 
+/* We include pcre.h before pcre_internal.h so that the PCRE library functions
+are declared as "import" for Windows by defining PCRE_EXP_DECL as "import".
+This is needed even though pcre_internal.h itself includes pcre.h, because it
+does so after it has set PCRE_EXP_DECL to "export" if it is not already set. */
+
 #include "pcre.h"
 #include "pcre_internal.h"
 #include "pcreposix.h"
@@ -133,7 +138,7 @@ static const int eint[] = {
   REG_INVARG,  /* inconsistent NEWLINE options */
   REG_BADPAT,  /* \g is not followed followed by an (optionally braced) non-zero number */
   REG_BADPAT,  /* a numbered reference must not be zero */
-  REG_BADPAT,  /* (*VERB) with an argument is not supported */
+  REG_BADPAT,  /* an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) */
   /* 60 */
   REG_BADPAT,  /* (*VERB) not recognized */
   REG_BADPAT,  /* number is too big */
@@ -141,7 +146,9 @@ static const int eint[] = {
   REG_BADPAT,  /* digit expected after (?+ */
   REG_BADPAT,  /* ] is an invalid data character in JavaScript compatibility mode */
   /* 65 */
-  REG_BADPAT   /* different names for subpatterns of the same number are not allowed */
+  REG_BADPAT,  /* different names for subpatterns of the same number are not allowed */
+  REG_BADPAT,  /* (*MARK) must have an argument */
+  REG_INVARG,  /* this version of PCRE is not compiled with PCRE_UCP support */
 };
 
 /* Table of texts corresponding to POSIX error codes */
@@ -245,6 +252,7 @@ if ((cflags & REG_NEWLINE) != 0)  options |= PCRE_MULTILINE;
 if ((cflags & REG_DOTALL) != 0)   options |= PCRE_DOTALL;
 if ((cflags & REG_NOSUB) != 0)    options |= PCRE_NO_AUTO_CAPTURE;
 if ((cflags & REG_UTF8) != 0)     options |= PCRE_UTF8;
+if ((cflags & REG_UCP) != 0)      options |= PCRE_UCP;
 if ((cflags & REG_UNGREEDY) != 0) options |= PCRE_UNGREEDY;
 
 preg->re_pcre = pcre_compile2(pattern, options, &errorcode, &errorptr,
@@ -334,13 +342,13 @@ if ((eflags & REG_STARTEND) != 0)
 else
   {
   so = 0;
-  eo = strlen(string);
+  eo = (int)strlen(string);
   }
 
 rc = pcre_exec((const pcre *)preg->re_pcre, NULL, string + so, (eo - so),
-  0, options, ovector, nmatch * 3);
+  0, options, ovector, (int)(nmatch * 3));
 
-if (rc == 0) rc = nmatch;    /* All captured slots were filled in */
+if (rc == 0) rc = (int)nmatch;    /* All captured slots were filled in */
 
 /* Successful match */
 
index 8ad58f5935b5e4d796de64bae9e9ddcf8f356417..b90e2ec6dc7303fb44b22d79bb0c568172889c17 100644 (file)
@@ -62,6 +62,7 @@ extern "C" {
 #define REG_STARTEND  0x0080   /* BSD feature: pass subject string by so,eo */
 #define REG_NOTEMPTY  0x0100   /* NOT defined by POSIX; maps to PCRE_NOTEMPTY */
 #define REG_UNGREEDY  0x0200   /* NOT defined by POSIX; maps to PCRE_UNGREEDY */
+#define REG_UCP       0x0400   /* NOT defined by POSIX; maps to PCRE_UCP */
 
 /* This is not used by PCRE, but by defining it we make it easier
 to slot PCRE into existing programs that make POSIX calls. */
index 420c2743256e2360e72c9350de724a10202beef7..99afab88bd3253a9dd29cad73b66efc8a853f9ee 100644 (file)
@@ -1,7 +1,8 @@
 /-- These are a few representative patterns whose lengths and offsets are to be 
 shown when the link size is 2. This is just a doublecheck test to ensure the 
 sizes don't go horribly wrong when something is changed. The pattern contents 
-are all themselves checked in other tests. --/
+are all themselves checked in other tests. Unicode, including property support, 
+is required for these tests. --/
 
 /((?i)b)/BM
 
@@ -121,4 +122,14 @@ are all themselves checked in other tests. --/
 
 /[^\xaa]/8BM
 
+/[^\d]/8WB
+
+/[[:^alpha:][:^cntrl:]]+/8WB
+
+/[[:^cntrl:][:^alpha:]]+/8WB
+
+/[[:alpha:]]+/8WB
+
+/[[:^alpha:]\S]+/8WB
+
 /-- End of testinput10 --/
index 94a18c9a4c067b63b083d7bd0d89fbe212af4cf5..cc94bed4e8b1525a9835820f9b5203e8d5d71ae0 100644 (file)
@@ -2,12 +2,12 @@
     of PCRE's API, error diagnostics, and the compiled code of some patterns.
     It also checks the non-Perl syntax the PCRE supports (Python, .NET, 
     Oniguruma). Finally, there are some tests where PCRE and Perl differ, 
-    either because PCRE can't be compatible, or there is potential Perl 
+    either because PCRE can't be compatible, or there is a possible Perl 
     bug. --/  
   
-/-- Originally, the Perl 5.10 things were in here too, but now I have separated
-    many (most?) of them out into test 11. However, there may still be some
-    that were overlooked. --/   
+/-- Originally, the Perl 5.10 and 5.11 things were in here too, but now I have 
+    separated many (most?) of them out into test 11. However, there may still 
+    be some that were overlooked. --/   
 
 /(a)b|/I
 
 
 /(?X)[\B]/
 
+/(?X)[\R]/
+
+/(?X)[\X]/
+
+/[\B]/BZ
+
+/[\R]/BZ
+
+/[\X]/BZ
+
 /[z-a]/
 
 /^*/
@@ -2279,8 +2289,6 @@ a random value. /Ix
 /a+b?(*THEN)c+(*FAIL)/C
     aaabccc
     
-/a(*PRUNE:XXX)b/
-
 /a(*MARK)b/ 
 
 /(?i:A{1,}\6666666666)/
@@ -3232,4 +3240,255 @@ a random value. /Ix
 
 /(?P<L1>(?P<L2>0|)|(?P>L2)(?P>L1))/
 
+/abc(*MARK:)pqr/
+
+/abc(*:)pqr/
+
+/abc(*FAIL:123)xyz/
+
+/--- This should, and does, fail. In Perl, it does not, which I think is a 
+     bug because replacing the B in the pattern by (B|D) does make it fail. ---/
+
+/A(*COMMIT)B/+K
+    ACABX
+
+/--- These should be different, but in Perl 5.11 are not, which I think
+     is a bug in Perl. ---/
+
+/A(*THEN)B|A(*THEN)C/K
+    AC
+
+/A(*PRUNE)B|A(*PRUNE)C/K
+    AC
+    
+/--- A whole lot of tests of verbs with arguments are here rather than in test
+     11 because Perl doesn't seem to follow its specification entirely 
+     correctly. ---/
+
+/--- Perl 5.11 sets $REGERROR on the AC failure case here; PCRE does not. It is
+     not clear how Perl defines "involved in the failure of the match". ---/ 
+
+/^(A(*THEN:A)B|C(*THEN:B)D)/K
+    AB
+    CD
+    ** Failers
+    AC
+    CB    
+    
+/--- Check the use of names for success and failure. PCRE doesn't show these 
+names for success, though Perl does, contrary to its spec. ---/
+
+/^(A(*PRUNE:A)B|C(*PRUNE:B)D)/K
+    AB
+    CD
+    ** Failers
+    AC
+    CB    
+    
+/--- An empty name does not pass back an empty string. It is the same as if no
+name were given. ---/ 
+
+/^(A(*PRUNE:)B|C(*PRUNE:B)D)/K
+    AB
+    CD 
+
+/--- PRUNE goes to next bumpalong; COMMIT does not. ---/
+    
+/A(*PRUNE:A)B/K
+    ACAB
+
+/(*MARK:A)(*PRUNE:B)(C|X)/K
+    C
+    D 
+
+/(*MARK:A)(*THEN:B)(C|X)/K
+    C
+    D 
+
+/--- This should fail, as the skip causes a bump to offset 3 (the skip) ---/
+
+/A(*MARK:A)A+(*SKIP)(B|Z) | AC/xK
+    AAAC
+
+/--- Same --/
+
+/A(*MARK:A)A+(*MARK:B)(*SKIP:B)(B|Z) | AC/xK
+    AAAC
+
+/--- This should fail; the SKIP advances by one, but when we get to AC, the
+     PRUNE kills it. ---/ 
+    
+/A(*PRUNE:A)A+(*SKIP:A)(B|Z) | AC/xK
+    AAAC
+
+/A(*:A)A+(*SKIP)(B|Z) | AC/xK
+    AAAC
+
+/--- This should fail, as a null name is the same as no name ---/
+
+/A(*MARK:A)A+(*SKIP:)(B|Z) | AC/xK
+    AAAC
+
+/--- This fails in PCRE, and I think that is in accordance with Perl's 
+     documentation, though in Perl it succeeds. ---/
+    
+/A(*MARK:A)A+(*SKIP:B)(B|Z) | AAC/xK
+    AAAC
+
+/--- Mark names can be duplicated ---/
+
+/A(*:A)B|X(*:A)Y/K
+    AABC
+    XXYZ 
+    
+/^A(*:A)B|^X(*:A)Y/K
+    ** Failers
+    XAQQ
+    
+/--- A check on what happens after hitting a mark and them bumping along to
+something that does not even start. Perl reports tags after the failures here, 
+though it does not when the individual letters are made into something 
+more complicated. ---/
+
+/A(*:A)B|XX(*:B)Y/K
+    AABC
+    XXYZ 
+    ** Failers
+    XAQQ  
+    XAQQXZZ  
+    AXQQQ 
+    AXXQQQ 
+    
+/--- COMMIT at the start of a pattern should be the same as an anchor. Perl 
+optimizations defeat this. So does the PCRE optimization unless we disable it 
+with \Y. ---/
+
+/(*COMMIT)ABC/
+    ABCDEFG
+    ** Failers
+    DEFGABC\Y  
+    
+/--- Repeat some tests with added studying. ---/
+
+/A(*COMMIT)B/+KS
+    ACABX
+/A(*THEN)B|A(*THEN)C/KS
+    AC
+
+/A(*PRUNE)B|A(*PRUNE)C/KS
+    AC
+
+/^(A(*THEN:A)B|C(*THEN:B)D)/KS
+    AB
+    CD
+    ** Failers
+    AC
+    CB    
+
+/^(A(*PRUNE:A)B|C(*PRUNE:B)D)/KS
+    AB
+    CD
+    ** Failers
+    AC
+    CB    
+
+/^(A(*PRUNE:)B|C(*PRUNE:B)D)/KS
+    AB
+    CD 
+
+/A(*PRUNE:A)B/KS
+    ACAB
+
+/(*MARK:A)(*PRUNE:B)(C|X)/KS
+    C
+    D 
+
+/(*MARK:A)(*THEN:B)(C|X)/KS
+    C
+    D 
+
+/A(*MARK:A)A+(*SKIP)(B|Z) | AC/xKS
+    AAAC
+
+/A(*MARK:A)A+(*MARK:B)(*SKIP:B)(B|Z) | AC/xKS
+    AAAC
+    
+/A(*PRUNE:A)A+(*SKIP:A)(B|Z) | AC/xKS
+    AAAC
+
+/A(*:A)A+(*SKIP)(B|Z) | AC/xKS
+    AAAC
+
+/A(*MARK:A)A+(*SKIP:)(B|Z) | AC/xKS
+    AAAC
+
+/A(*MARK:A)A+(*SKIP:B)(B|Z) | AAC/xKS
+    AAAC
+
+/A(*:A)B|XX(*:B)Y/KS
+    AABC
+    XXYZ 
+    ** Failers
+    XAQQ  
+    XAQQXZZ  
+    AXQQQ 
+    AXXQQQ 
+    
+/(*COMMIT)ABC/
+    ABCDEFG
+    ** Failers
+    DEFGABC\Y  
+
+/^(ab (c+(*THEN)cd) | xyz)/x
+    abcccd  
+
+/^(ab (c+(*PRUNE)cd) | xyz)/x
+    abcccd  
+
+/^(ab (c+(*FAIL)cd) | xyz)/x
+    abcccd  
+    
+/--- Perl 5.11 gets some of these wrong ---/ 
+
+/(?>.(*ACCEPT))*?5/
+    abcde
+
+/(.(*ACCEPT))*?5/
+    abcde
+
+/(.(*ACCEPT))5/
+    abcde
+
+/(.(*ACCEPT))*5/
+    abcde
+
+/A\NB./BZ
+  ACBD
+  ** Failers
+  A\nB
+  ACB\n   
+
+/A\NB./sBZ
+  ACBD
+  ACB\n 
+  ** Failers
+  A\nB  
+  
+/A\NB/<crlf>
+  A\nB
+  A\rB
+  ** Failers
+  A\r\nB    
+
+/\R+b/BZ
+
+/\R+\n/BZ
+
+/\R+\d/BZ
+
+/\d*\R/BZ
+
+/\s*\R/BZ
+
 /-- End of testinput2 --/
index 68795e609569d59b3d39c90c6b88e9f300a7efeb..5e200b3e31986046e5c0c54cbada0917125e2edc 100644 (file)
@@ -745,4 +745,53 @@ can't tell the difference.) --/
 /X\W{3}X/8
     \PX
 
+/\h/SI
+
+/\h/SI8
+    ABC\x{09}
+    ABC\x{20}
+    ABC\x{a0}
+    ABC\x{1680}
+    ABC\x{180e}
+    ABC\x{2000}
+    ABC\x{202f} 
+    ABC\x{205f} 
+    ABC\x{3000} 
+
+/\v/SI
+
+/\v/SI8
+    ABC\x{0a}
+    ABC\x{0b}
+    ABC\x{0c}
+    ABC\x{0d}
+    ABC\x{85}
+    ABC\x{2028}
+
+/\R/SI
+
+/\R/SI8
+
+/\h*A/SI8
+    CDBABC
+    
+/\v+A/SI8
+
+/\s?xxx\s/8SI
+
+/\sxxx\s/8T1
+    AB\x{85}xxx\x{a0}XYZ
+    AB\x{a0}xxx\x{85}XYZ
+
+/\sxxx\s/I8ST1
+    AB\x{85}xxx\x{a0}XYZ
+    AB\x{a0}xxx\x{85}XYZ
+
+/\S \S/8T1
+    \x{a2} \x{84} 
+
+/\S \S/I8ST1
+    \x{a2} \x{84} 
+    A Z 
+
 /-- End of testinput5 --/
index 759018a3aaee971e1070843b96f736f58db07229..e923e009961ed1706938013fa8aa4f592f559288 100644 (file)
 /\p{Avestan}\p{Bamum}\p{Egyptian_Hieroglyphs}\p{Imperial_Aramaic}\p{Inscriptional_Pahlavi}\p{Inscriptional_Parthian}\p{Javanese}\p{Kaithi}\p{Lisu}\p{Meetei_Mayek}\p{Old_South_Arabian}\p{Old_Turkic}\p{Samaritan}\p{Tai_Tham}\p{Tai_Viet}/8
     \x{10b00}\x{a6ef}\x{13007}\x{10857}\x{10b78}\x{10b58}\x{a980}\x{110c1}\x{a4ff}\x{abc0}\x{10a7d}\x{10c48}\x{0800}\x{1aad}\x{aac0}
 
+/^\w+/8W
+    Az_\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee}
+
+/^[[:xdigit:]]*/8W
+    1a\x{660}\x{bef}\x{16ee}
+  
+/^\d+/8W
+    1\x{660}\x{bef}\x{16ee}
+  
+/^[[:digit:]]+/8W
+    1\x{660}\x{bef}\x{16ee}
+
+/^>\s+/8W
+    >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 
+  
+/^>\pZ+/8W
+    >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 
+  
+/^>[[:space:]]*/8W
+    >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 
+
+/^>[[:blank:]]*/8W
+    >\x{20}\x{a0}\x{1680}\x{180e}\x{2000}\x{202f}\x{9}\x{b}\x{2028} 
+
+/^[[:alpha:]]*/8W
+    Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}
+
+/^[[:alnum:]]*/8W
+    Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee}
+
+/^[[:cntrl:]]*/8W
+    \x{0}\x{09}\x{1f}\x{7f}\x{9f} 
+
+/^[[:graph:]]*/8W
+    A\x{a1}\x{a0}
+
+/^[[:print:]]*/8W
+    A z\x{a0}\x{a1}
+
+/^[[:punct:]]*/8W
+    .+\x{a1}\x{a0}
+
+/\p{Zs}*?\R/
+    ** Failers
+    a\xFCb   
+
+/\p{Zs}*\R/                                                                    
+    ** Failers 
+    a\xFCb   
+
 /-- End of testinput6 --/
index 590420c8ea107dfc1c1ef39fd8e3329c1487d244..8d312e028750408cdded4b4baca2738caf3f1c5e 100644 (file)
     ** Failers 
     \x{1d79}\x{a77d} 
 
+/^\p{Xan}/8
+    ABCD
+    1234
+    \x{6ca}
+    \x{a6c}
+    \x{10a7}   
+    ** Failers
+    _ABC   
+
+/^\p{Xan}+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+    ** Failers
+    _ABC   
+
+/^\p{Xan}*/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+    
+/^\p{Xan}{2,9}/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+    
+/^[\p{Xan}]/8
+    ABCD1234_
+    1234abcd_
+    \x{6ca}
+    \x{a6c}
+    \x{10a7}   
+    ** Failers
+    _ABC   
+/^[\p{Xan}]+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+    ** Failers
+    _ABC   
+
+/^>\p{Xsp}/8
+    >\x{1680}\x{2028}\x{0b}
+    ** Failers
+    \x{0b} 
+
+/^>\p{Xsp}+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+
+/^>\p{Xsp}*/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+    
+/^>\p{Xsp}{2,9}/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+    
+/^>[\p{Xsp}]/8
+    >\x{2028}\x{0b}
+/^>[\p{Xsp}]+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+
+/^>\p{Xps}/8
+    >\x{1680}\x{2028}\x{0b}
+    >\x{a0} 
+    ** Failers
+    \x{0b} 
+
+/^>\p{Xps}+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+
+/^>\p{Xps}+?/8
+    >\x{1680}\x{2028}\x{0b}
+
+/^>\p{Xps}*/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+    
+/^>\p{Xps}{2,9}/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+    
+/^>\p{Xps}{2,9}?/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+    
+/^>[\p{Xps}]/8
+    >\x{2028}\x{0b}
+/^>[\p{Xps}]+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+
+/^\p{Xwd}/8
+    ABCD
+    1234
+    \x{6ca}
+    \x{a6c}
+    \x{10a7}
+    _ABC    
+    ** Failers
+    [] 
+
+/^\p{Xwd}+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+
+/^\p{Xwd}*/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+    
+/^\p{Xwd}{2,9}/8
+    A_12\x{6ca}\x{a6c}\x{10a7}
+    
+/^[\p{Xwd}]/8
+    ABCD1234_
+    1234abcd_
+    \x{6ca}
+    \x{a6c}
+    \x{10a7}   
+    _ABC 
+    ** Failers
+    []   
+/^[\p{Xwd}]+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+
+/-- Unicode properties for \b abd \B --/
+
+/\b...\B/8W
+    abc_
+    \x{37e}abc\x{376} 
+    \x{37e}\x{376}\x{371}\x{393}\x{394} 
+    !\x{c0}++\x{c1}\x{c2} 
+    !\x{c0}+++++ 
+
+/-- Without PCRE_UCP, non-ASCII always fail, even if < 256  --/
+
+/\b...\B/8
+    abc_
+    ** Failers 
+    \x{37e}abc\x{376} 
+    \x{37e}\x{376}\x{371}\x{393}\x{394} 
+    !\x{c0}++\x{c1}\x{c2} 
+    !\x{c0}+++++ 
+
+/-- With PCRE_UCP, non-UTF8 chars that are < 256 still check properties  --/
+
+/\b...\B/W
+    abc_
+    !\x{c0}++\x{c1}\x{c2} 
+    !\x{c0}+++++ 
+
 /-- End of testinput9 --/ 
index a0db64035ac86b94c7f2643337c6c97e6ed10c44..4994584ddf519a40aee7e70e32939f6d212f4ab9 100644 (file)
@@ -1,7 +1,8 @@
 /-- These are a few representative patterns whose lengths and offsets are to be 
 shown when the link size is 2. This is just a doublecheck test to ensure the 
 sizes don't go horribly wrong when something is changed. The pattern contents 
-are all themselves checked in other tests. --/
+are all themselves checked in other tests. Unicode, including property support, 
+is required for these tests. --/
 
 /((?i)b)/BM
 Memory allocation (code space): 21
@@ -666,4 +667,44 @@ Memory allocation (code space): 40
  39     End
 ------------------------------------------------------------------
 
+/[^\d]/8WB
+------------------------------------------------------------------
+  0  11 Bra
+  3     [^\p{Nd}]
+ 11  11 Ket
+ 14     End
+------------------------------------------------------------------
+
+/[[:^alpha:][:^cntrl:]]+/8WB
+------------------------------------------------------------------
+  0  44 Bra
+  3     [ -~\x80-\xff\P{L}]+
+ 44  44 Ket
+ 47     End
+------------------------------------------------------------------
+
+/[[:^cntrl:][:^alpha:]]+/8WB
+------------------------------------------------------------------
+  0  44 Bra
+  3     [ -~\x80-\xff\P{L}]+
+ 44  44 Ket
+ 47     End
+------------------------------------------------------------------
+
+/[[:alpha:]]+/8WB
+------------------------------------------------------------------
+  0  12 Bra
+  3     [\p{L}]+
+ 12  12 Ket
+ 15     End
+------------------------------------------------------------------
+
+/[[:^alpha:]\S]+/8WB
+------------------------------------------------------------------
+  0  15 Bra
+  3     [\P{L}\P{Xsp}]+
+ 15  15 Ket
+ 18     End
+------------------------------------------------------------------
+
 /-- End of testinput10 --/
index c29bd5fd3847502ca1c0f2bc014fc439335236f3..2baa6e923eeec63b683dd16749f2adba85332fec 100644 (file)
@@ -2,12 +2,12 @@
     of PCRE's API, error diagnostics, and the compiled code of some patterns.
     It also checks the non-Perl syntax the PCRE supports (Python, .NET, 
     Oniguruma). Finally, there are some tests where PCRE and Perl differ, 
-    either because PCRE can't be compatible, or there is potential Perl 
+    either because PCRE can't be compatible, or there is a possible Perl 
     bug. --/  
   
-/-- Originally, the Perl 5.10 things were in here too, but now I have separated
-    many (most?) of them out into test 11. However, there may still be some
-    that were overlooked. --/   
+/-- Originally, the Perl 5.10 and 5.11 things were in here too, but now I have 
+    separated many (most?) of them out into test 11. However, there may still 
+    be some that were overlooked. --/   
 
 /(a)b|/I
 Capturing subpattern count = 1
@@ -103,6 +103,36 @@ Failed: missing terminating ] for character class at offset 5
 /(?X)[\B]/
 Failed: invalid escape sequence in character class at offset 6
 
+/(?X)[\R]/
+Failed: invalid escape sequence in character class at offset 6
+
+/(?X)[\X]/
+Failed: invalid escape sequence in character class at offset 6
+
+/[\B]/BZ
+------------------------------------------------------------------
+        Bra
+        B
+        Ket
+        End
+------------------------------------------------------------------
+
+/[\R]/BZ
+------------------------------------------------------------------
+        Bra
+        R
+        Ket
+        End
+------------------------------------------------------------------
+
+/[\X]/BZ
+------------------------------------------------------------------
+        Bra
+        X
+        Ket
+        End
+------------------------------------------------------------------
+
 /[z-a]/
 Failed: range out of order in character class at offset 3
 
@@ -3198,19 +3228,19 @@ Failed: POSIX collating elements are not supported at offset 0
 Failed: POSIX named classes are supported only within a class at offset 0
 
 /\l/I
-Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1
+Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1
 
 /\L/I
-Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1
+Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1
 
 /\N{name}/I
-Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1
+Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1
 
 /\u/I
-Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1
+Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1
 
 /\U/I
-Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1
+Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1
 
 /[/I
 Failed: missing terminating ] for character class at offset 1
@@ -8667,11 +8697,8 @@ No match
 +13   ^  ^      (*FAIL)
 No match
     
-/a(*PRUNE:XXX)b/
-Failed: (*VERB) with an argument is not supported at offset 8
-
 /a(*MARK)b/ 
-Failed: (*VERB) not recognized at offset 7
+Failed: (*MARK) must have an argument at offset 7
 
 /(?i:A{1,}\6666666666)/
 Failed: number is too big at offset 19
@@ -10668,4 +10695,435 @@ No match
 /(?P<L1>(?P<L2>0|)|(?P>L2)(?P>L1))/
 Failed: recursive call could loop indefinitely at offset 31
 
+/abc(*MARK:)pqr/
+Failed: (*MARK) must have an argument at offset 10
+
+/abc(*:)pqr/
+Failed: (*MARK) must have an argument at offset 6
+
+/abc(*FAIL:123)xyz/
+Failed: an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) at offset 13
+
+/--- This should, and does, fail. In Perl, it does not, which I think is a 
+     bug because replacing the B in the pattern by (B|D) does make it fail. ---/
+
+/A(*COMMIT)B/+K
+    ACABX
+No match
+
+/--- These should be different, but in Perl 5.11 are not, which I think
+     is a bug in Perl. ---/
+
+/A(*THEN)B|A(*THEN)C/K
+    AC
+ 0: AC
+
+/A(*PRUNE)B|A(*PRUNE)C/K
+    AC
+No match
+    
+/--- A whole lot of tests of verbs with arguments are here rather than in test
+     11 because Perl doesn't seem to follow its specification entirely 
+     correctly. ---/
+
+/--- Perl 5.11 sets $REGERROR on the AC failure case here; PCRE does not. It is
+     not clear how Perl defines "involved in the failure of the match". ---/ 
+
+/^(A(*THEN:A)B|C(*THEN:B)D)/K
+    AB
+ 0: AB
+ 1: AB
+    CD
+ 0: CD
+ 1: CD
+    ** Failers
+No match
+    AC
+No match
+    CB    
+No match, mark = B
+    
+/--- Check the use of names for success and failure. PCRE doesn't show these 
+names for success, though Perl does, contrary to its spec. ---/
+
+/^(A(*PRUNE:A)B|C(*PRUNE:B)D)/K
+    AB
+ 0: AB
+ 1: AB
+    CD
+ 0: CD
+ 1: CD
+    ** Failers
+No match
+    AC
+No match, mark = A
+    CB    
+No match, mark = B
+    
+/--- An empty name does not pass back an empty string. It is the same as if no
+name were given. ---/ 
+
+/^(A(*PRUNE:)B|C(*PRUNE:B)D)/K
+    AB
+ 0: AB
+ 1: AB
+    CD 
+ 0: CD
+ 1: CD
+
+/--- PRUNE goes to next bumpalong; COMMIT does not. ---/
+    
+/A(*PRUNE:A)B/K
+    ACAB
+ 0: AB
+
+/(*MARK:A)(*PRUNE:B)(C|X)/K
+    C
+ 0: C
+ 1: C
+MK: A
+    D 
+No match, mark = B
+
+/(*MARK:A)(*THEN:B)(C|X)/K
+    C
+ 0: C
+ 1: C
+MK: A
+    D 
+No match, mark = B
+
+/--- This should fail, as the skip causes a bump to offset 3 (the skip) ---/
+
+/A(*MARK:A)A+(*SKIP)(B|Z) | AC/xK
+    AAAC
+No match
+
+/--- Same --/
+
+/A(*MARK:A)A+(*MARK:B)(*SKIP:B)(B|Z) | AC/xK
+    AAAC
+No match
+
+/--- This should fail; the SKIP advances by one, but when we get to AC, the
+     PRUNE kills it. ---/ 
+    
+/A(*PRUNE:A)A+(*SKIP:A)(B|Z) | AC/xK
+    AAAC
+No match
+
+/A(*:A)A+(*SKIP)(B|Z) | AC/xK
+    AAAC
+No match
+
+/--- This should fail, as a null name is the same as no name ---/
+
+/A(*MARK:A)A+(*SKIP:)(B|Z) | AC/xK
+    AAAC
+No match
+
+/--- This fails in PCRE, and I think that is in accordance with Perl's 
+     documentation, though in Perl it succeeds. ---/
+    
+/A(*MARK:A)A+(*SKIP:B)(B|Z) | AAC/xK
+    AAAC
+No match
+
+/--- Mark names can be duplicated ---/
+
+/A(*:A)B|X(*:A)Y/K
+    AABC
+ 0: AB
+MK: A
+    XXYZ 
+ 0: XY
+MK: A
+    
+/^A(*:A)B|^X(*:A)Y/K
+    ** Failers
+No match
+    XAQQ
+No match, mark = A
+    
+/--- A check on what happens after hitting a mark and them bumping along to
+something that does not even start. Perl reports tags after the failures here, 
+though it does not when the individual letters are made into something 
+more complicated. ---/
+
+/A(*:A)B|XX(*:B)Y/K
+    AABC
+ 0: AB
+MK: A
+    XXYZ 
+ 0: XXY
+MK: B
+    ** Failers
+No match
+    XAQQ  
+No match
+    XAQQXZZ  
+No match
+    AXQQQ 
+No match
+    AXXQQQ 
+No match
+    
+/--- COMMIT at the start of a pattern should be the same as an anchor. Perl 
+optimizations defeat this. So does the PCRE optimization unless we disable it 
+with \Y. ---/
+
+/(*COMMIT)ABC/
+    ABCDEFG
+ 0: ABC
+    ** Failers
+No match
+    DEFGABC\Y  
+No match
+    
+/--- Repeat some tests with added studying. ---/
+
+/A(*COMMIT)B/+KS
+    ACABX
+No match
+/A(*THEN)B|A(*THEN)C/KS
+    AC
+ 0: AC
+
+/A(*PRUNE)B|A(*PRUNE)C/KS
+    AC
+No match
+
+/^(A(*THEN:A)B|C(*THEN:B)D)/KS
+    AB
+ 0: AB
+ 1: AB
+    CD
+ 0: CD
+ 1: CD
+    ** Failers
+No match
+    AC
+No match
+    CB    
+No match, mark = B
+
+/^(A(*PRUNE:A)B|C(*PRUNE:B)D)/KS
+    AB
+ 0: AB
+ 1: AB
+    CD
+ 0: CD
+ 1: CD
+    ** Failers
+No match
+    AC
+No match, mark = A
+    CB    
+No match, mark = B
+
+/^(A(*PRUNE:)B|C(*PRUNE:B)D)/KS
+    AB
+ 0: AB
+ 1: AB
+    CD 
+ 0: CD
+ 1: CD
+
+/A(*PRUNE:A)B/KS
+    ACAB
+ 0: AB
+
+/(*MARK:A)(*PRUNE:B)(C|X)/KS
+    C
+ 0: C
+ 1: C
+MK: A
+    D 
+No match
+
+/(*MARK:A)(*THEN:B)(C|X)/KS
+    C
+ 0: C
+ 1: C
+MK: A
+    D 
+No match
+
+/A(*MARK:A)A+(*SKIP)(B|Z) | AC/xKS
+    AAAC
+No match
+
+/A(*MARK:A)A+(*MARK:B)(*SKIP:B)(B|Z) | AC/xKS
+    AAAC
+No match
+    
+/A(*PRUNE:A)A+(*SKIP:A)(B|Z) | AC/xKS
+    AAAC
+No match
+
+/A(*:A)A+(*SKIP)(B|Z) | AC/xKS
+    AAAC
+No match
+
+/A(*MARK:A)A+(*SKIP:)(B|Z) | AC/xKS
+    AAAC
+No match
+
+/A(*MARK:A)A+(*SKIP:B)(B|Z) | AAC/xKS
+    AAAC
+No match
+
+/A(*:A)B|XX(*:B)Y/KS
+    AABC
+ 0: AB
+MK: A
+    XXYZ 
+ 0: XXY
+MK: B
+    ** Failers
+No match
+    XAQQ  
+No match
+    XAQQXZZ  
+No match
+    AXQQQ 
+No match
+    AXXQQQ 
+No match
+    
+/(*COMMIT)ABC/
+    ABCDEFG
+ 0: ABC
+    ** Failers
+No match
+    DEFGABC\Y  
+No match
+
+/^(ab (c+(*THEN)cd) | xyz)/x
+    abcccd  
+No match
+
+/^(ab (c+(*PRUNE)cd) | xyz)/x
+    abcccd  
+No match
+
+/^(ab (c+(*FAIL)cd) | xyz)/x
+    abcccd  
+No match
+    
+/--- Perl 5.11 gets some of these wrong ---/ 
+
+/(?>.(*ACCEPT))*?5/
+    abcde
+ 0: a
+
+/(.(*ACCEPT))*?5/
+    abcde
+ 0: a
+ 1: a
+
+/(.(*ACCEPT))5/
+    abcde
+ 0: a
+ 1: a
+
+/(.(*ACCEPT))*5/
+    abcde
+ 0: a
+ 1: a
+
+/A\NB./BZ
+------------------------------------------------------------------
+        Bra
+        A
+        Any
+        B
+        Any
+        Ket
+        End
+------------------------------------------------------------------
+  ACBD
+ 0: ACBD
+  ** Failers
+No match
+  A\nB
+No match
+  ACB\n   
+No match
+
+/A\NB./sBZ
+------------------------------------------------------------------
+        Bra
+        A
+        Any
+        B
+        AllAny
+        Ket
+        End
+------------------------------------------------------------------
+  ACBD
+ 0: ACBD
+  ACB\n 
+ 0: ACB\x0a
+  ** Failers
+No match
+  A\nB  
+No match
+  
+/A\NB/<crlf>
+  A\nB
+ 0: A\x0aB
+  A\rB
+ 0: A\x0dB
+  ** Failers
+No match
+  A\r\nB    
+No match
+
+/\R+b/BZ
+------------------------------------------------------------------
+        Bra
+        \R++
+        b
+        Ket
+        End
+------------------------------------------------------------------
+
+/\R+\n/BZ
+------------------------------------------------------------------
+        Bra
+        \R+
+        \x0a
+        Ket
+        End
+------------------------------------------------------------------
+
+/\R+\d/BZ
+------------------------------------------------------------------
+        Bra
+        \R++
+        \d
+        Ket
+        End
+------------------------------------------------------------------
+
+/\d*\R/BZ
+------------------------------------------------------------------
+        Bra
+        \d*+
+        \R
+        Ket
+        End
+------------------------------------------------------------------
+
+/\s*\R/BZ
+------------------------------------------------------------------
+        Bra
+        \s*+
+        \R
+        Ket
+        End
+------------------------------------------------------------------
+
 /-- End of testinput2 --/
index 9d815ffa825d9955a068a4623330a3fceac17646..b3ce48a0dd84e456e494adbb943fc4e97bed0834 100644 (file)
@@ -2076,4 +2076,150 @@ Partial match: abcde
     \PX
 Partial match: X
 
+/\h/SI
+Capturing subpattern count = 0
+No options
+No first char
+No need char
+Subject length lower bound = 1
+Starting byte set: \x09 \x20 \xa0 
+
+/\h/SI8
+Capturing subpattern count = 0
+Options: utf8
+No first char
+No need char
+Subject length lower bound = 1
+Starting byte set: \x09 \x20 \xc2 \xe1 \xe2 \xe3 
+    ABC\x{09}
+ 0: \x{09}
+    ABC\x{20}
+ 0:  
+    ABC\x{a0}
+ 0: \x{a0}
+    ABC\x{1680}
+ 0: \x{1680}
+    ABC\x{180e}
+ 0: \x{180e}
+    ABC\x{2000}
+ 0: \x{2000}
+    ABC\x{202f} 
+ 0: \x{202f}
+    ABC\x{205f} 
+ 0: \x{205f}
+    ABC\x{3000} 
+ 0: \x{3000}
+
+/\v/SI
+Capturing subpattern count = 0
+No options
+No first char
+No need char
+Subject length lower bound = 1
+Starting byte set: \x0a \x0b \x0c \x0d \x85 
+
+/\v/SI8
+Capturing subpattern count = 0
+Options: utf8
+No first char
+No need char
+Subject length lower bound = 1
+Starting byte set: \x0a \x0b \x0c \x0d \xc2 \xe2 
+    ABC\x{0a}
+ 0: \x{0a}
+    ABC\x{0b}
+ 0: \x{0b}
+    ABC\x{0c}
+ 0: \x{0c}
+    ABC\x{0d}
+ 0: \x{0d}
+    ABC\x{85}
+ 0: \x{85}
+    ABC\x{2028}
+ 0: \x{2028}
+
+/\R/SI
+Capturing subpattern count = 0
+No options
+No first char
+No need char
+Subject length lower bound = 2
+Starting byte set: \x0a \x0b \x0c \x0d \x85 
+
+/\R/SI8
+Capturing subpattern count = 0
+Options: utf8
+No first char
+No need char
+Subject length lower bound = 2
+Starting byte set: \x0a \x0b \x0c \x0d \xc2 \xe2 
+
+/\h*A/SI8
+Capturing subpattern count = 0
+Options: utf8
+No first char
+Need char = 'A'
+Subject length lower bound = 1
+Starting byte set: \x09 \x20 A \xc2 \xe1 \xe2 \xe3 
+    CDBABC
+ 0: A
+    
+/\v+A/SI8
+Capturing subpattern count = 0
+Options: utf8
+No first char
+Need char = 'A'
+Subject length lower bound = 2
+Starting byte set: \x0a \x0b \x0c \x0d \xc2 \xe2 
+
+/\s?xxx\s/8SI
+Capturing subpattern count = 0
+Options: utf8
+No first char
+Need char = 'x'
+Subject length lower bound = 4
+Starting byte set: \x09 \x0a \x0c \x0d \x20 x 
+
+/\sxxx\s/8T1
+    AB\x{85}xxx\x{a0}XYZ
+ 0: \x{85}xxx\x{a0}
+    AB\x{a0}xxx\x{85}XYZ
+ 0: \x{a0}xxx\x{85}
+
+/\sxxx\s/I8ST1
+Capturing subpattern count = 0
+Options: utf8
+No first char
+Need char = 'x'
+Subject length lower bound = 5
+Starting byte set: \x09 \x0a \x0c \x0d \x20 \xc2 
+    AB\x{85}xxx\x{a0}XYZ
+ 0: \x{85}xxx\x{a0}
+    AB\x{a0}xxx\x{85}XYZ
+ 0: \x{a0}xxx\x{85}
+
+/\S \S/8T1
+    \x{a2} \x{84} 
+ 0: \x{a2} \x{84}
+
+/\S \S/I8ST1
+Capturing subpattern count = 0
+Options: utf8
+No first char
+Need char = ' '
+Subject length lower bound = 3
+Starting byte set: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0b \x0e 
+  \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d 
+  \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 
+  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e 
+  f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \xc0 \xc1 \xc2 \xc3 
+  \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 
+  \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 
+  \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 
+  \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff 
+    \x{a2} \x{84} 
+ 0: \x{a2} \x{84}
+    A Z 
+ 0: A Z
+
 /-- End of testinput5 --/
index b4176eb57960fd1c995e417a5d902f9d695e0d8c..e000083b06a791a7722609c782c750a204c3ab00 100644 (file)
@@ -1285,4 +1285,72 @@ No match
     \x{10b00}\x{a6ef}\x{13007}\x{10857}\x{10b78}\x{10b58}\x{a980}\x{110c1}\x{a4ff}\x{abc0}\x{10a7d}\x{10c48}\x{0800}\x{1aad}\x{aac0}
  0: \x{10b00}\x{a6ef}\x{13007}\x{10857}\x{10b78}\x{10b58}\x{a980}\x{110c1}\x{a4ff}\x{abc0}\x{10a7d}\x{10c48}\x{800}\x{1aad}\x{aac0}
 
+/^\w+/8W
+    Az_\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee}
+ 0: Az_\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee}
+
+/^[[:xdigit:]]*/8W
+    1a\x{660}\x{bef}\x{16ee}
+ 0: 1a
+  
+/^\d+/8W
+    1\x{660}\x{bef}\x{16ee}
+ 0: 1\x{660}\x{bef}
+  
+/^[[:digit:]]+/8W
+    1\x{660}\x{bef}\x{16ee}
+ 0: 1\x{660}\x{bef}
+
+/^>\s+/8W
+    >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 
+ 0: > \x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{09}
+  
+/^>\pZ+/8W
+    >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 
+ 0: > \x{a0}\x{1680}\x{2028}\x{2029}\x{202f}
+  
+/^>[[:space:]]*/8W
+    >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 
+ 0: > \x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{09}\x{0b}
+
+/^>[[:blank:]]*/8W
+    >\x{20}\x{a0}\x{1680}\x{180e}\x{2000}\x{202f}\x{9}\x{b}\x{2028} 
+ 0: > \x{a0}\x{1680}\x{180e}\x{2000}\x{202f}\x{09}
+
+/^[[:alpha:]]*/8W
+    Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}
+ 0: Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}
+
+/^[[:alnum:]]*/8W
+    Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee}
+ 0: Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee}
+
+/^[[:cntrl:]]*/8W
+    \x{0}\x{09}\x{1f}\x{7f}\x{9f} 
+ 0: \x{00}\x{09}\x{1f}\x{7f}
+
+/^[[:graph:]]*/8W
+    A\x{a1}\x{a0}
+ 0: A
+
+/^[[:print:]]*/8W
+    A z\x{a0}\x{a1}
+ 0: A z
+
+/^[[:punct:]]*/8W
+    .+\x{a1}\x{a0}
+ 0: .+
+
+/\p{Zs}*?\R/
+    ** Failers
+No match
+    a\xFCb   
+No match
+
+/\p{Zs}*\R/                                                                    
+    ** Failers 
+No match
+    a\xFCb   
+No match
+
 /-- End of testinput6 --/
index 851e3f020fd90c9a07586477dca0fcac2d06d8de..cb70f1c25935d222d534be02f654e45c5e58df30 100644 (file)
@@ -1674,4 +1674,364 @@ No match
     \x{1d79}\x{a77d} 
 No match
 
+/^\p{Xan}/8
+    ABCD
+ 0: A
+    1234
+ 0: 1
+    \x{6ca}
+ 0: \x{6ca}
+    \x{a6c}
+ 0: \x{a6c}
+    \x{10a7}   
+ 0: \x{10a7}
+    ** Failers
+No match
+    _ABC   
+No match
+
+/^\p{Xan}+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}
+ 1: ABCD1234\x{6ca}\x{a6c}
+ 2: ABCD1234\x{6ca}
+ 3: ABCD1234
+ 4: ABCD123
+ 5: ABCD12
+ 6: ABCD1
+ 7: ABCD
+ 8: ABC
+ 9: AB
+10: A
+    ** Failers
+No match
+    _ABC   
+No match
+
+/^\p{Xan}*/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}
+ 1: ABCD1234\x{6ca}\x{a6c}
+ 2: ABCD1234\x{6ca}
+ 3: ABCD1234
+ 4: ABCD123
+ 5: ABCD12
+ 6: ABCD1
+ 7: ABCD
+ 8: ABC
+ 9: AB
+10: A
+11: 
+    
+/^\p{Xan}{2,9}/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}
+ 1: ABCD1234
+ 2: ABCD123
+ 3: ABCD12
+ 4: ABCD1
+ 5: ABCD
+ 6: ABC
+ 7: AB
+    
+/^[\p{Xan}]/8
+    ABCD1234_
+ 0: A
+    1234abcd_
+ 0: 1
+    \x{6ca}
+ 0: \x{6ca}
+    \x{a6c}
+ 0: \x{a6c}
+    \x{10a7}   
+ 0: \x{10a7}
+    ** Failers
+No match
+    _ABC   
+No match
+/^[\p{Xan}]+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}
+ 1: ABCD1234\x{6ca}\x{a6c}
+ 2: ABCD1234\x{6ca}
+ 3: ABCD1234
+ 4: ABCD123
+ 5: ABCD12
+ 6: ABCD1
+ 7: ABCD
+ 8: ABC
+ 9: AB
+10: A
+    ** Failers
+No match
+    _ABC   
+No match
+
+/^>\p{Xsp}/8
+    >\x{1680}\x{2028}\x{0b}
+ 0: >\x{1680}
+    ** Failers
+No match
+    \x{0b} 
+No match
+
+/^>\p{Xsp}+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}
+ 4: > \x{09}\x{0a}\x{0c}
+ 5: > \x{09}\x{0a}
+ 6: > \x{09}
+ 7: > 
+
+/^>\p{Xsp}*/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}
+ 4: > \x{09}\x{0a}\x{0c}
+ 5: > \x{09}\x{0a}
+ 6: > \x{09}
+ 7: > 
+ 8: >
+    
+/^>\p{Xsp}{2,9}/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}
+ 4: > \x{09}\x{0a}\x{0c}
+ 5: > \x{09}\x{0a}
+ 6: > \x{09}
+    
+/^>[\p{Xsp}]/8
+    >\x{2028}\x{0b}
+ 0: >\x{2028}
+/^>[\p{Xsp}]+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}
+ 4: > \x{09}\x{0a}\x{0c}
+ 5: > \x{09}\x{0a}
+ 6: > \x{09}
+ 7: > 
+
+/^>\p{Xps}/8
+    >\x{1680}\x{2028}\x{0b}
+ 0: >\x{1680}
+    >\x{a0} 
+ 0: >\x{a0}
+    ** Failers
+No match
+    \x{0b} 
+No match
+
+/^>\p{Xps}+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 4: > \x{09}\x{0a}\x{0c}\x{0d}
+ 5: > \x{09}\x{0a}\x{0c}
+ 6: > \x{09}\x{0a}
+ 7: > \x{09}
+ 8: > 
+
+/^>\p{Xps}+?/8
+    >\x{1680}\x{2028}\x{0b}
+ 0: >\x{1680}\x{2028}\x{0b}
+ 1: >\x{1680}\x{2028}
+ 2: >\x{1680}
+
+/^>\p{Xps}*/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 4: > \x{09}\x{0a}\x{0c}\x{0d}
+ 5: > \x{09}\x{0a}\x{0c}
+ 6: > \x{09}\x{0a}
+ 7: > \x{09}
+ 8: > 
+ 9: >
+    
+/^>\p{Xps}{2,9}/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 4: > \x{09}\x{0a}\x{0c}\x{0d}
+ 5: > \x{09}\x{0a}\x{0c}
+ 6: > \x{09}\x{0a}
+ 7: > \x{09}
+    
+/^>\p{Xps}{2,9}?/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 4: > \x{09}\x{0a}\x{0c}\x{0d}
+ 5: > \x{09}\x{0a}\x{0c}
+ 6: > \x{09}\x{0a}
+ 7: > \x{09}
+    
+/^>[\p{Xps}]/8
+    >\x{2028}\x{0b}
+ 0: >\x{2028}
+/^>[\p{Xps}]+/8
+    > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b}
+ 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}
+ 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}
+ 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}
+ 4: > \x{09}\x{0a}\x{0c}\x{0d}
+ 5: > \x{09}\x{0a}\x{0c}
+ 6: > \x{09}\x{0a}
+ 7: > \x{09}
+ 8: > 
+
+/^\p{Xwd}/8
+    ABCD
+ 0: A
+    1234
+ 0: 1
+    \x{6ca}
+ 0: \x{6ca}
+    \x{a6c}
+ 0: \x{a6c}
+    \x{10a7}
+ 0: \x{10a7}
+    _ABC    
+ 0: _
+    ** Failers
+No match
+    [] 
+No match
+
+/^\p{Xwd}+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 1: ABCD1234\x{6ca}\x{a6c}\x{10a7}
+ 2: ABCD1234\x{6ca}\x{a6c}
+ 3: ABCD1234\x{6ca}
+ 4: ABCD1234
+ 5: ABCD123
+ 6: ABCD12
+ 7: ABCD1
+ 8: ABCD
+ 9: ABC
+10: AB
+11: A
+
+/^\p{Xwd}*/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 1: ABCD1234\x{6ca}\x{a6c}\x{10a7}
+ 2: ABCD1234\x{6ca}\x{a6c}
+ 3: ABCD1234\x{6ca}
+ 4: ABCD1234
+ 5: ABCD123
+ 6: ABCD12
+ 7: ABCD1
+ 8: ABCD
+ 9: ABC
+10: AB
+11: A
+12: 
+    
+/^\p{Xwd}{2,9}/8
+    A_12\x{6ca}\x{a6c}\x{10a7}
+ 0: A_12\x{6ca}\x{a6c}\x{10a7}
+ 1: A_12\x{6ca}\x{a6c}
+ 2: A_12\x{6ca}
+ 3: A_12
+ 4: A_1
+ 5: A_
+    
+/^[\p{Xwd}]/8
+    ABCD1234_
+ 0: A
+    1234abcd_
+ 0: 1
+    \x{6ca}
+ 0: \x{6ca}
+    \x{a6c}
+ 0: \x{a6c}
+    \x{10a7}   
+ 0: \x{10a7}
+    _ABC 
+ 0: _
+    ** Failers
+No match
+    []   
+No match
+/^[\p{Xwd}]+/8
+    ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_
+ 1: ABCD1234\x{6ca}\x{a6c}\x{10a7}
+ 2: ABCD1234\x{6ca}\x{a6c}
+ 3: ABCD1234\x{6ca}
+ 4: ABCD1234
+ 5: ABCD123
+ 6: ABCD12
+ 7: ABCD1
+ 8: ABCD
+ 9: ABC
+10: AB
+11: A
+
+/-- Unicode properties for \b abd \B --/
+
+/\b...\B/8W
+    abc_
+ 0: abc
+    \x{37e}abc\x{376} 
+ 0: abc
+    \x{37e}\x{376}\x{371}\x{393}\x{394} 
+ 0: \x{376}\x{371}\x{393}
+    !\x{c0}++\x{c1}\x{c2} 
+ 0: ++\x{c1}
+    !\x{c0}+++++ 
+ 0: \x{c0}++
+
+/-- Without PCRE_UCP, non-ASCII always fail, even if < 256  --/
+
+/\b...\B/8
+    abc_
+ 0: abc
+    ** Failers 
+ 0: Fai
+    \x{37e}abc\x{376} 
+No match
+    \x{37e}\x{376}\x{371}\x{393}\x{394} 
+No match
+    !\x{c0}++\x{c1}\x{c2} 
+No match
+    !\x{c0}+++++ 
+No match
+
+/-- With PCRE_UCP, non-UTF8 chars that are < 256 still check properties  --/
+
+/\b...\B/W
+    abc_
+ 0: abc
+    !\x{c0}++\x{c1}\x{c2} 
+ 0: ++\xc1
+    !\x{c0}+++++ 
+ 0: \xc0++
+
 /-- End of testinput9 --/