./ ADD NAME=XCLASS8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains an internal function that is used to match an extended
class. It is used by both PCREXEC8() and pcre_def_exec(). */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*       Match character against an XCLASS        *
*************************************************/

/* This function is called to match a character against an extended class that
might contain values > 255 and/or Unicode properties.

Arguments:
  c           the character
  data        points to the flag byte of the XCLASS data

Returns:      TRUE if character matches, else FALSE
*/

BOOL
PRIV(xclass)(int c, const pcre_uchar *data, BOOL utf)
{
int t;
BOOL negated = (*data & XCL_NOT) != 0;

(void)utf;
#ifdef COMPILE_PCRE8
/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */
utf = TRUE;
#endif

/* Character values < 256 are matched against a bitmap, if one is present. If
not, we still carry on, because there may be ranges that start below 256 in the
additional data. */

if (c < 256)
  {
  if ((*data & XCL_MAP) != 0 &&
    (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0)
    return !negated; /* char found */
  }

/* First skip the bit map if present. Then match against the list of Unicode
properties or large chars or ranges that end with a large char. We won't ever
encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */

if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar);

while ((t = *data++) != XCL_END)
  {
  int x, y;
  if (t == XCL_SINGLE)
    {
#ifdef SUPPORT_UTF
    if (utf)
      {
      GETCHARINC(x, data); /* macro generates multiple statements */
      }
    else
#endif
      x = *data++;
    if (c == x) return !negated;
    }
  else if (t == XCL_RANGE)
    {
#ifdef SUPPORT_UTF
    if (utf)
      {
      GETCHARINC(x, data); /* macro generates multiple statements */
      GETCHARINC(y, data); /* macro generates multiple statements */
      }
    else
#endif
      {
      x = *data++;
      y = *data++;
      }
    if (c >= x && c <= y) return !negated;
    }

#ifdef SUPPORT_UCP
  else  /* XCL_PROP & XCL_NOTPROP */
    {
    const ucd_record *prop = GET_UCD(c);

    switch(*data)
      {
      case PT_ANY:
      if (t == XCL_PROP) return !negated;
      break;

      case PT_LAMP:
      if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
           prop->chartype == ucp_Lt) == (t == XCL_PROP)) return !negated;
      break;

      case PT_GC:
      if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == (t == XCL_PROP))
        return !negated;
      break;

      case PT_PC:
      if ((data[1] == prop->chartype) == (t == XCL_PROP)) return !negated;
      break;

      case PT_SC:
      if ((data[1] == prop->script) == (t == XCL_PROP)) return !negated;
      break;

      case PT_ALNUM:
      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
           PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (t == XCL_PROP))
        return !negated;
      break;

      case PT_SPACE:    /* Perl space */
      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
           c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
             == (t == XCL_PROP))
        return !negated;
      break;

      case PT_PXSPACE:  /* POSIX space */
      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
           c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
           c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP))
        return !negated;
      break;

      case PT_WORD:
      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
           PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
             == (t == XCL_PROP))
        return !negated;
      break;

      /* This should never occur, but compilers may mutter if there is no
      default. */

      default:
      return FALSE;
      }

    data += 2;
    }
#endif  /* SUPPORT_UCP */
  }

return negated;   /* char did not match */
}

/* End of XCLASS8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_xclass.c converted to XCLASS8*/
/*autoconv-0013 XCLASS8 line: 42 pcre_exec replaced by PCREXEC8*/
/*autoconv-0010 XCLASS8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 XCLASS8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 XCLASS8 line: 52 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 XCLASS8 line: 201 pcre_xclass replaced by XCLASS8*/
./ ADD NAME=FULLINF8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function FULLINF8(), which returns
information about a compiled pattern. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*        Return info about compiled pattern      *
*************************************************/

/* This is a newer "info" function which has an extensible interface so
that additional items can be added compatibly.

Arguments:
  argument_re      points to compiled code
  extra_data       points extra data, or NULL
  what             what information is required
  where            where to put the information

Returns:           0 if data returned, negative on error
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
FULLINF8(const pcre *argument_re, const pcre_extra *extra_data,
  int what, void *where)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data,
  int what, void *where)
#endif
{
const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
const pcre_study_data *study = NULL;

if (re == NULL || where == NULL) return PCRE_ERROR_NULL;

if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
  study = (const pcre_study_data *)extra_data->study_data;

/* Check that the first field in the block is the magic number. If it is not,
return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
means that the pattern is likely compiled with different endianness. */

if (re->magic_number != MAGIC_NUMBER)
  return re->magic_number == REVERSED_MAGIC_NUMBER?
    PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;

/* Check that this pattern was compiled in the correct bit mode */

if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;

switch (what)
  {
  case PCRE_INFO_OPTIONS:
  *((unsigned long int *)where) = re->options & PUBLIC_COMPILE_OPTIONS;
  break;

  case PCRE_INFO_SIZE:
  *((size_t *)where) = re->size;
  break;

  case PCRE_INFO_STUDYSIZE:
  *((size_t *)where) = (study == NULL)? 0 : study->size;
  break;

  case PCRE_INFO_JITSIZE:
#ifdef SUPPORT_JIT
  *((size_t *)where) =
      (extra_data != NULL &&
      (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
      extra_data->executable_jit != NULL)?
    PRIV(jit_get_size)(extra_data->executable_jit) : 0;
#else
  *((size_t *)where) = 0;
#endif
  break;

  case PCRE_INFO_CAPTURECOUNT:
  *((int *)where) = re->top_bracket;
  break;

  case PCRE_INFO_BACKREFMAX:
  *((int *)where) = re->top_backref;
  break;

  case PCRE_INFO_FIRSTBYTE:
  *((int *)where) =
    ((re->flags & PCRE_FIRSTSET) != 0)? re->first_char :
    ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
  break;

  /* Make sure we pass back the pointer to the bit vector in the external
  block, not the internal copy (with flipped integer fields). */

  case PCRE_INFO_FIRSTTABLE:
  *((const pcre_uint8 **)where) =
    (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)?
      ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL;
  break;

  case PCRE_INFO_MINLENGTH:
  *((int *)where) =
    (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)?
      (int)(study->minlength) : -1;
  break;

  case PCRE_INFO_JIT:
  *((int *)where) = extra_data != NULL &&
                    (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
                    extra_data->executable_jit != NULL;
  break;

  case PCRE_INFO_LASTLITERAL:
  *((int *)where) =
    ((re->flags & PCRE_REQCHSET) != 0)? re->req_char : -1;
  break;

  case PCRE_INFO_NAMEENTRYSIZE:
  *((int *)where) = re->name_entry_size;
  break;

  case PCRE_INFO_NAMECOUNT:
  *((int *)where) = re->name_count;
  break;

  case PCRE_INFO_NAMETABLE:
  *((const pcre_uchar **)where) = (const pcre_uchar *)re + re->name_table_offset;
  break;

  case PCRE_INFO_DEFAULT_TABLES:
  *((const pcre_uint8 **)where) = (const pcre_uint8 *)(PRIV(default_tables));
  break;

  /* From release 8.00 this will always return TRUE because NOPARTIAL is
  no longer ever set (the restrictions have been removed). */

  case PCRE_INFO_OKPARTIAL:
  *((int *)where) = (re->flags & PCRE_NOPARTIAL) == 0;
  break;

  case PCRE_INFO_JCHANGED:
  *((int *)where) = (re->flags & PCRE_JCHANGED) != 0;
  break;

  case PCRE_INFO_HASCRORLF:
  *((int *)where) = (re->flags & PCRE_HASCRORLF) != 0;
  break;

  case PCRE_INFO_MAXLOOKBEHIND:
  *((int *)where) = re->max_lookbehind;
  break;

  default: return PCRE_ERROR_BADOPTION;
  }

return 0;
}

/* End of FULLINF8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_fullinfo.c converted to FULLINF8*/
/*autoconv-0013 FULLINF8 line: 41 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0010 FULLINF8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 FULLINF8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 FULLINF8 line: 52 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 FULLINF8 line: 73 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 FULLINF8 line: 209 pcre_fullinfo replaced by FULLINF8*/
./ ADD NAME=PCREDEMO 
/*************************************************
*           PCRE DEMONSTRATION PROGRAM           *
*************************************************/

/* This is a demonstration program to illustrate the most straightforward ways
of calling the PCRE regular expression library from a C program. See the
pcresample documentation for a short discussion ("man pcresample" if you have
the PCRE man pages installed).

In Unix-like environments, if PCRE is installed in your standard system
libraries, you should be able to compile this program using this command:

gcc -Wall PCREDEMO.c -lpcre -o PCREDEMO

If PCRE is not installed in a standard place, it is likely to be installed with
support for the pkg-config mechanism. If you have pkg-config, you can compile
this program using this command:

gcc -Wall PCREDEMO.c `pkg-config --cflags --libs libpcre` -o PCREDEMO

If you do not have pkg-config, you may have to use this:

gcc -Wall PCREDEMO.c -I/usr/local/include -L/usr/local/lib \
  -R/usr/local/lib -lpcre -o PCREDEMO

Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and
library files for PCRE are installed on your system. Only some operating
systems (e.g. Solaris) use the -R option.

Building under Windows:

If you want to statically link this program against 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. So in this environment, uncomment the following line. */

/* #define PCRE_STATIC */

#include <stdio.h>
#include <string.h>
#include "PCRE.h"

#define OVECCOUNT 30    /* should be a multiple of 3 */


int main(int argc, char **argv)
{
pcre *re;
const char *error;
char *pattern;
char *subject;
unsigned char *name_table;
unsigned int option_bits;
int erroffset;
int find_all;
int crlf_is_newline;
int namecount;
int name_entry_size;
int ovector[OVECCOUNT];
int subject_length;
int rc, i;
int utf8;


/**************************************************************************
* First, sort out the command line. There is only one possible option at  *
* the moment, "-g" to request repeated matching to find all occurrences,  *
* like Perl's /g option. We set the variable find_all to a non-zero value *
* if the -g option is present. Apart from that, there must be exactly two *
* arguments.                                                              *
**************************************************************************/

find_all = 0;
for (i = 1; i < argc; i++)
  {
  if (strcmp(argv[i], "-g") == 0) find_all = 1;
    else break;
  }

/* After the options, we require exactly two arguments, which are the pattern,
and the subject string. */

if (argc - i != 2)
  {
  printf("Two arguments required: a regex and a subject string\n");
  return 1;
  }

pattern = argv[i];
subject = argv[i+1];
subject_length = (int)strlen(subject);


/*************************************************************************
* Now we are going to compile the regular expression pattern, and handle *
* and errors that are detected.                                          *
*************************************************************************/

re = COMPILE8(
  pattern,              /* the pattern */
  0,                    /* default options */
  &error,               /* for error message */
  &erroffset,           /* for error offset */
  NULL);                /* use default character tables */

/* Compilation failed: print the error message and exit */

if (re == NULL)
  {
  printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
  return 1;
  }


/*************************************************************************
* If the compilation succeeded, we call PCRE again, in order to do a     *
* pattern match against the subject string. This does just ONE match. If *
* further matching is needed, it will be done below.                     *
*************************************************************************/

rc = PCREXEC8(
  re,                   /* the compiled pattern */
  NULL,                 /* no extra data - we didn't study the pattern */
  subject,              /* the subject string */
  subject_length,       /* the length of the subject */
  0,                    /* start at offset 0 in the subject */
  0,                    /* default options */
  ovector,              /* output vector for substring information */
  OVECCOUNT);           /* number of elements in the output vector */

/* Matching failed: handle error cases */

if (rc < 0)
  {
  switch(rc)
    {
    case PCRE_ERROR_NOMATCH: printf("No match\n"); break;
    /*
    Handle other special cases if you like
    */
    default: printf("Matching error %d\n", rc); break;
    }
  pcre_free(re);     /* Release memory used for the compiled pattern */
  return 1;
  }

/* Match succeded */

printf("\nMatch succeeded at offset %d\n", ovector[0]);


/*************************************************************************
* We have found the first match within the subject string. If the output *
* vector wasn't big enough, say so. Then output any substrings that were *
* captured.                                                              *
*************************************************************************/

/* The output vector wasn't big enough */

if (rc == 0)
  {
  rc = OVECCOUNT/3;
  printf("ovector only has room for %d captured substrings\n", rc - 1);
  }

/* Show substrings stored in the output vector by number. Obviously, in a real
application you might want to do things other than print them. */

for (i = 0; i < rc; i++)
  {
  char *substring_start = subject + ovector[2*i];
  int substring_length = ovector[2*i+1] - ovector[2*i];
  printf("%2d: %.*s\n", i, substring_length, substring_start);
  }


/**************************************************************************
* That concludes the basic part of this demonstration program. We have    *
* compiled a pattern, and performed a single match. The code that follows *
* shows first how to access named substrings, and then how to code for    *
* repeated matches on the same subject.                                   *
**************************************************************************/

/* See if there are any named substrings, and if so, show them by name. First
we have to extract the count of named parentheses from the pattern. */

(void)FULLINF8(
  re,                   /* the compiled pattern */
  NULL,                 /* no extra data - we didn't study the pattern */
  PCRE_INFO_NAMECOUNT,  /* number of named substrings */
  &namecount);          /* where to put the answer */

if (namecount <= 0) printf("No named substrings\n"); else
  {
  unsigned char *tabptr;
  printf("Named substrings\n");

  /* Before we can access the substrings, we must extract the table for
  translating names to numbers, and the size of each entry in the table. */

  (void)FULLINF8(
    re,                       /* the compiled pattern */
    NULL,                     /* no extra data - we didn't study the pattern */
    PCRE_INFO_NAMETABLE,      /* address of the table */
    &name_table);             /* where to put the answer */

  (void)FULLINF8(
    re,                       /* the compiled pattern */
    NULL,                     /* no extra data - we didn't study the pattern */
    PCRE_INFO_NAMEENTRYSIZE,  /* size of each entry in the table */
    &name_entry_size);        /* where to put the answer */

  /* Now we can scan the table and, for each entry, print the number, the name,
  and the substring itself. */

  tabptr = name_table;
  for (i = 0; i < namecount; i++)
    {
    int n = (tabptr[0] << 8) | tabptr[1];
    printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,
      ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]);
    tabptr += name_entry_size;
    }
  }


/*************************************************************************
* If the "-g" option was given on the command line, we want to continue  *
* to search for additional matches in the subject string, in a similar   *
* way to the /g option in Perl. This turns out to be trickier than you   *
* might think because of the possibility of matching an empty string.    *
* What happens is as follows:                                            *
*                                                                        *
* If the previous match was NOT for an empty string, we can just start   *
* the next match at the end of the previous one.                         *
*                                                                        *
* If the previous match WAS for an empty string, we can't do that, as it *
* would lead to an infinite loop. Instead, a special call of PCREXEC8() *
* is made with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set.    *
* The first of these tells PCRE that an empty string at the start of the *
* subject is not a valid match; other possibilities must be tried. The   *
* second flag restricts PCRE to one match attempt at the initial string  *
* position. If this match succeeds, an alternative to the empty string   *
* match has been found, and we can print it and proceed round the loop,  *
* advancing by the length of whatever was found. If this match does not  *
* succeed, we still stay in the loop, advancing by just one character.   *
* In UTF-8 mode, which can be set by (*UTF8) in the pattern, this may be *
* more than one byte.                                                    *
*                                                                        *
* However, there is a complication concerned with newlines. When the     *
* newline convention is such that CRLF is a valid newline, we must       *
* advance by two characters rather than one. The newline convention can  *
* be set in the regex by (*CR), etc.; if not, we must find the default.  *
*************************************************************************/

if (!find_all)     /* Check for -g */
  {
  pcre_free(re);   /* Release the memory used for the compiled pattern */
  return 0;        /* Finish unless -g was given */
  }

/* Before running the loop, check for UTF-8 and whether CRLF is a valid newline
sequence. First, find the options with which the regex was compiled; extract
the UTF-8 state, and mask off all but the newline options. */

(void)FULLINF8(re, NULL, PCRE_INFO_OPTIONS, &option_bits);
utf8 = option_bits & PCRE_UTF8;
option_bits &= PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_CRLF|
               PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF;

/* If no newline options were set, find the default newline convention from the
build configuration. */

if (option_bits == 0)
  {
  int d;
  (void)CONFIG8(PCRE_CONFIG_NEWLINE, &d);
  /* Note that these values are always the ASCII ones, even in
  EBCDIC environments. CR = 13, NL = 10. */
  option_bits = (d == 13)? PCRE_NEWLINE_CR :
          (d == 10)? PCRE_NEWLINE_LF :
          (d == (13<<8 | 10))? PCRE_NEWLINE_CRLF :
          (d == -2)? PCRE_NEWLINE_ANYCRLF :
          (d == -1)? PCRE_NEWLINE_ANY : 0;
  }

/* See if CRLF is a valid newline sequence. */

crlf_is_newline =
     option_bits == PCRE_NEWLINE_ANY ||
     option_bits == PCRE_NEWLINE_CRLF ||
     option_bits == PCRE_NEWLINE_ANYCRLF;

/* Loop for second and subsequent matches */

for (;;)
  {
  int options = 0;                 /* Normally no options */
  int start_offset = ovector[1];   /* Start at end of previous match */

  /* If the previous match was for an empty string, we are finished if we are
  at the end of the subject. Otherwise, arrange to run another match at the
  same point to see if a non-empty match can be found. */

  if (ovector[0] == ovector[1])
    {
    if (ovector[0] == subject_length) break;
    options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED;
    }

  /* Run the next matching operation */

  rc = PCREXEC8(
    re,                   /* the compiled pattern */
    NULL,                 /* no extra data - we didn't study the pattern */
    subject,              /* the subject string */
    subject_length,       /* the length of the subject */
    start_offset,         /* starting offset in the subject */
    options,              /* options */
    ovector,              /* output vector for substring information */
    OVECCOUNT);           /* number of elements in the output vector */

  /* This time, a result of NOMATCH isn't an error. If the value in "options"
  is zero, it just means we have found all possible matches, so the loop ends.
  Otherwise, it means we have failed to find a non-empty-string match at a
  point where there was a previous empty-string match. In this case, we do what
  Perl does: advance the matching position by one character, and continue. We
  do this by setting the "end of previous match" offset, because that is picked
  up at the top of the loop as the point at which to start again.

  There are two complications: (a) When CRLF is a valid newline sequence, and
  the current position is just before it, advance by an extra byte. (b)
  Otherwise we must ensure that we skip an entire UTF-8 character if we are in
  UTF-8 mode. */

  if (rc == PCRE_ERROR_NOMATCH)
    {
    if (options == 0) break;                    /* All matches found */
    ovector[1] = start_offset + 1;              /* Advance one byte */
    if (crlf_is_newline &&                      /* If CRLF is newline & */
        start_offset < subject_length - 1 &&    /* we are at CRLF, */
        subject[start_offset] == '\r' &&
        subject[start_offset + 1] == '\n')
      ovector[1] += 1;                          /* Advance by one more. */
    else if (utf8)                              /* Otherwise, ensure we */
      {                                         /* advance a whole UTF-8 */
      while (ovector[1] < subject_length)       /* character. */
        {
        if ((subject[ovector[1]] & 0xc0) != 0x80) break;
        ovector[1] += 1;
        }
      }
    continue;    /* Go round the loop again */
    }

  /* Other matching errors are not recoverable. */

  if (rc < 0)
    {
    printf("Matching error %d\n", rc);
    pcre_free(re);    /* Release memory used for the compiled pattern */
    return 1;
    }

  /* Match succeded */

  printf("\nMatch succeeded again at offset %d\n", ovector[0]);

  /* The match succeeded, but the output vector wasn't big enough. */

  if (rc == 0)
    {
    rc = OVECCOUNT/3;
    printf("ovector only has room for %d captured substrings\n", rc - 1);
    }

  /* As before, show substrings stored in the output vector by number, and then
  also any named substrings. */

  for (i = 0; i < rc; i++)
    {
    char *substring_start = subject + ovector[2*i];
    int substring_length = ovector[2*i+1] - ovector[2*i];
    printf("%2d: %.*s\n", i, substring_length, substring_start);
    }

  if (namecount <= 0) printf("No named substrings\n"); else
    {
    unsigned char *tabptr = name_table;
    printf("Named substrings\n");
    for (i = 0; i < namecount; i++)
      {
      int n = (tabptr[0] << 8) | tabptr[1];
      printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,
        ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]);
      tabptr += name_entry_size;
      }
    }
  }      /* End of loop to find second and subsequent matches */

printf("\n");
pcre_free(re);       /* Release memory used for the compiled pattern */
return 0;
}

/* End of PCREDEMO.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcredemo.c converted to PCREDEMO*/
/*autoconv-0013 PCREDEMO line: 13 pcredemo replaced by PCREDEMO*/
/*autoconv-0013 PCREDEMO line: 13 pcredemo replaced by PCREDEMO*/
/*autoconv-0013 PCREDEMO line: 19 pcredemo replaced by PCREDEMO*/
/*autoconv-0013 PCREDEMO line: 19 pcredemo replaced by PCREDEMO*/
/*autoconv-0013 PCREDEMO line: 23 pcredemo replaced by PCREDEMO*/
/*autoconv-0013 PCREDEMO line: 24 pcredemo replaced by PCREDEMO*/
/*autoconv-0011 PCREDEMO line: 41 pcre.h replaced by PCRE.h*/
/*autoconv-0016 PCREDEMO line: 41 <pcre.h> replaced by "pcre.h"/*autoconv-0013 PCREDEMO line: 99 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCREDEMO line: 121 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREDEMO line: 187 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREDEMO line: 201 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREDEMO line: 207 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREDEMO line: 238 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREDEMO line: 266 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREDEMO line: 277 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCREDEMO line: 313 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREDEMO line: 406 pcredemo replaced by PCREDEMO*/
./ ADD NAME=INTERNA8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/


/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

/* This header contains definitions that are shared between the different
modules, but which are not relevant to the exported API. This includes some
functions whose names all begin with "_pcre_" or "_pcre16_" depending on
the PRIV macro. */

#ifndef PCRE_INTERNAL_H
#define PCRE_INTERNAL_H

/* Define PCRE_DEBUG to get debugging output on stdout. */

#if 0
#define PCRE_DEBUG
#endif

/* PCRE is compiled as an 8 bit library if it is not requested otherwise. */
#ifndef COMPILE_PCRE16
#define COMPILE_PCRE8
#endif

/* If SUPPORT_UCP is defined, SUPPORT_UTF must also be defined. The
"configure" script ensures this, but not everybody uses "configure". */

#if defined SUPPORT_UCP && !(defined SUPPORT_UTF)
#define SUPPORT_UTF 1
#endif

/* We define SUPPORT_UTF if SUPPORT_UTF8 is enabled for compatibility
reasons with existing code. */

#if defined SUPPORT_UTF8 && !(defined SUPPORT_UTF)
#define SUPPORT_UTF 1
#endif

/* Fixme: SUPPORT_UTF8 should be eventually disappear from the code.
Until then we define it if SUPPORT_UTF is defined. */

#if defined SUPPORT_UTF && !(defined SUPPORT_UTF8)
#define SUPPORT_UTF8 1
#endif

/* We do not support both EBCDIC and UTF-8/16 at the same time. The "configure"
script prevents both being selected, but not everybody uses "configure". */

#if defined EBCDIC && defined SUPPORT_UTF
#error The use of both EBCDIC and SUPPORT_UTF8/16 is not supported.
#endif

/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
inline, and there are *still* stupid compilers about that don't like indented
pre-processor statements, or at least there were when I first wrote this. After
all, it had only been about 10 years then...

It turns out that the Mac Debugging.h header also defines the macro DPRINTF, so
be absolutely sure we get our version. */

#undef DPRINTF
#ifdef PCRE_DEBUG
#define DPRINTF(p) printf p
#else
#define DPRINTF(p) /* Nothing */
#endif


/* Standard C headers plus the external interface definition. The only time
setjmp and stdarg are used is when NO_RECURSE is set. */

#include <ctype.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* When compiling a DLL for Windows, the exported symbols have to be declared
using some MS magic. I found some useful information on this web page:
http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the
information there, using __declspec(dllexport) without "extern" we have a
definition; with "extern" we have a declaration. The settings here override the
setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL,
which is all that is needed for applications (they just import the symbols). We
use:

  PCRE_EXP_DECL       for declarations
  PCRE_EXP_DEFN       for definitions of exported functions
  PCRE_EXP_DATA_DEFN  for definitions of exported variables

The reason for the two DEFN macros is that in non-Windows environments, one
does not want to have "extern" before variable definitions because it leads to
compiler warnings. So we distinguish between functions and variables. In
Windows, the two should always be the same.

The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that PCRETEST,
which is an application, but needs to import this file in order to "peek" at
internals, can #include pcre.h first to get an application's-eye view.

In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon,
special-purpose environments) might want to stick other stuff in front of
exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and
PCRE_EXP_DATA_DEFN only if they are not already set. */

#ifndef PCRE_EXP_DECL
#  ifdef _WIN32
#    ifndef PCRE_STATIC
#      define PCRE_EXP_DECL       extern __declspec(dllexport)
#      define PCRE_EXP_DEFN       __declspec(dllexport)
#      define PCRE_EXP_DATA_DEFN  __declspec(dllexport)
#    else
#      define PCRE_EXP_DECL       extern
#      define PCRE_EXP_DEFN
#      define PCRE_EXP_DATA_DEFN
#    endif
#  else
#    ifdef __cplusplus
#      define PCRE_EXP_DECL       extern "C"
#    else
#      define PCRE_EXP_DECL       extern
#    endif
#    ifndef PCRE_EXP_DEFN
#      define PCRE_EXP_DEFN       PCRE_EXP_DECL
#    endif
#    ifndef PCRE_EXP_DATA_DEFN
#      define PCRE_EXP_DATA_DEFN
#    endif
#  endif
#endif

/* When compiling with the MSVC compiler, it is sometimes necessary to include
a "calling convention" before exported function names. (This is secondhand
information; I know nothing about MSVC myself). For example, something like

  void __cdecl function(....)

might be needed. In order so make this easy, all the exported functions have
PCRE_CALL_CONVENTION just before their names. It is rarely needed; if not
set, we ensure here that it has no effect. */

#ifndef PCRE_CALL_CONVENTION
#define PCRE_CALL_CONVENTION
#endif

/* We need to have types that specify unsigned 8, 16 and 32-bit integers. We
cannot determine these outside the compilation (e.g. by running a program as
part of "configure") because PCRE is often cross-compiled for use on other
systems. Instead we make use of the maximum sizes that are available at
preprocessor time in standard C environments. */

typedef unsigned char pcre_uint8;

#if USHRT_MAX == 65535
  typedef unsigned short pcre_uint16;
  typedef short pcre_int16;
#elif UINT_MAX == 65535
  typedef unsigned int pcre_uint16;
  typedef int pcre_int16;
#else
  #error Cannot determine a type for 16-bit unsigned integers
#endif

#if UINT_MAX == 4294967295
  typedef unsigned int pcre_uint32;
  typedef int pcre_int32;
#elif ULONG_MAX == 4294967295
  typedef unsigned long int pcre_uint32;
  typedef long int pcre_int32;
#else
  #error Cannot determine a type for 32-bit unsigned integers
#endif

/* When checking for integer overflow in COMPILE8(), we need to handle
large integers. If a 64-bit integer type is available, we can use that.
Otherwise we have to cast to double, which of course requires floating point
arithmetic. Handle this by defining a macro for the appropriate type. If
stdint.h is available, include it; it may define INT64_MAX. Systems that do not
have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set
by "configure". */

#if HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#endif

#if defined INT64_MAX || defined int64_t
#define INT64_OR_DOUBLE int64_t
#else
#define INT64_OR_DOUBLE double
#endif

/* All character handling must be done as unsigned characters. Otherwise there
are problems with top-bit-set characters and functions such as isspace().
However, we leave the interface to the outside world as char * or short *,
because that should make things easier for callers. This character type is
called pcre_uchar.

The IN_UCHARS macro multiply its argument with the byte size of the current
pcre_uchar type. Useful for memcpy and such operations, whose require the
byte size of their input/output buffers.

The MAX_255 macro checks whether its pcre_uchar input is less than 256.

The TABLE_GET macro is designed for accessing elements of tables whose contain
exactly 256 items. When the character is able to contain more than 256
items, some check is needed before accessing these tables.
*/

#ifdef COMPILE_PCRE8

typedef unsigned char pcre_uchar;
#define IN_UCHARS(x) (x)
#define MAX_255(c) 1
#define TABLE_GET(c, table, default) ((table)[c])

#else

#ifdef COMPILE_PCRE16
#if USHRT_MAX != 65535
/* This is a warning message. Change PCRE_UCHAR16 to a 16 bit data type in
pcre.h(.in) and disable (comment out) this message. */
#error Warning: PCRE_UCHAR16 is not a 16 bit data type.
#endif

typedef pcre_uint16 pcre_uchar;
#define IN_UCHARS(x) ((x) << 1)
#define MAX_255(c) ((c) <= 255u)
#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))

#else
#error Unsupported compiling mode
#endif /* COMPILE_PCRE16 */

#endif /* COMPILE_PCRE8 */

/* This is an unsigned int value that no character can ever have. UTF-8
characters only go up to 0x7fffffff (though Unicode doesn't go beyond
0x0010ffff). */

#define NOTACHAR 0xffffffff

/* PCRE is able to support several different kinds of newline (CR, LF, CRLF,
"any" and "anycrlf" at present). The following macros are used to package up
testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various
modules to indicate in which datablock the parameters exist, and what the
start/end of string field names are. */

#define NLTYPE_FIXED    0     /* Newline is a fixed length string */
#define NLTYPE_ANY      1     /* Newline is any Unicode line ending */
#define NLTYPE_ANYCRLF  2     /* Newline is CR, LF, or CRLF */

/* This macro checks for a newline at the given position */

#define IS_NEWLINE(p) \
  ((NLBLOCK->nltype != NLTYPE_FIXED)? \
    ((p) < NLBLOCK->PSEND && \
     PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \
       &(NLBLOCK->nllen), utf)) \
    : \
    ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \
     (p)[0] == NLBLOCK->nl[0] && \
     (NLBLOCK->nllen == 1 || (p)[1] == NLBLOCK->nl[1]) \
    ) \
  )

/* This macro checks for a newline immediately preceding the given position */

#define WAS_NEWLINE(p) \
  ((NLBLOCK->nltype != NLTYPE_FIXED)? \
    ((p) > NLBLOCK->PSSTART && \
     PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \
       &(NLBLOCK->nllen), utf)) \
    : \
    ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
     (p)[-NLBLOCK->nllen] == NLBLOCK->nl[0] && \
     (NLBLOCK->nllen == 1 || (p)[-NLBLOCK->nllen+1] == NLBLOCK->nl[1]) \
    ) \
  )

/* When PCRE is compiled as a C++ library, the subject pointer can be replaced
with a custom type. This makes it possible, for example, to allow PCREXEC8()
to process subject strings that are discontinuous by using a smart pointer
class. It must always be possible to inspect all of the subject string in
PCREXEC8() because of the way it backtracks. Two macros are required in the
normal case, for sign-unspecified and unsigned char pointers. The former is
used for the external interface and appears in pcre.h, which is why its name
must begin with PCRE_. */

#ifdef CUSTOM_SUBJECT_PTR
#define PCRE_PUCHAR CUSTOM_SUBJECT_PTR
#else
#define PCRE_PUCHAR const pcre_uchar *
#endif

/* Include the public PCRE header and the definitions of UCP character property
values. */

#include "PCRE.h"
#include "UCP.h"

/* When compiling for use with the Virtual Pascal compiler, these functions
need to have their names changed. PCRE must be compiled with the -DVPCOMPAT
option on the command line. */

#ifdef VPCOMPAT
#define strlen(s)        _strlen(s)
#define strncmp(s1,s2,m) _strncmp(s1,s2,m)
#define memcmp(s,c,n)    _memcmp(s,c,n)
#define memcpy(d,s,n)    _memcpy(d,s,n)
#define memmove(d,s,n)   _memmove(d,s,n)
#define memset(s,c,n)    _memset(s,c,n)
#else  /* VPCOMPAT */

/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(),
define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY
is set. Otherwise, include an emulating function for those systems that have
neither (there some non-Unix environments where this is the case). */

#ifndef HAVE_MEMMOVE
#undef  memmove        /* some systems may have a macro */
#ifdef HAVE_BCOPY
#define memmove(a, b, c) bcopy(b, a, c)
#else  /* HAVE_BCOPY */
static void *
pcre_memmove(void *d, const void *s, size_t n)
{
size_t i;
unsigned char *dest = (unsigned char *)d;
const unsigned char *src = (const unsigned char *)s;
if (dest > src)
  {
  dest += n;
  src += n;
  for (i = 0; i < n; ++i) *(--dest) = *(--src);
  return (void *)dest;
  }
else
  {
  for (i = 0; i < n; ++i) *dest++ = *src++;
  return (void *)(dest - n);
  }
}
#define memmove(a, b, c) pcre_memmove(a, b, c)
#endif   /* not HAVE_BCOPY */
#endif   /* not HAVE_MEMMOVE */
#endif   /* not VPCOMPAT */


/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored
in big-endian order) by default. These are used, for example, to link from the
start of a subpattern to its alternatives and its end. The use of 2 bytes per
offset limits the size of the compiled regex to around 64K, which is big enough
for almost everybody. However, I received a request for an even bigger limit.
For this reason, and also to make the code easier to maintain, the storing and
loading of offsets from the byte string is now handled by the macros that are
defined here.

The macros are controlled by the value of LINK_SIZE. This defaults to 2 in
the config.h file, but can be overridden by using -D on the command line. This
is automated on Unix systems via the "configure" command. */

#ifdef COMPILE_PCRE8

#if LINK_SIZE == 2

#define PUT(a,n,d)   \
  (a[n] = (d) >> 8), \
  (a[(n)+1] = (d) & 255)

#define GET(a,n) \
  (((a)[n] << 8) | (a)[(n)+1])

#define MAX_PATTERN_SIZE (1 << 16)


#elif LINK_SIZE == 3

#define PUT(a,n,d)       \
  (a[n] = (d) >> 16),    \
  (a[(n)+1] = (d) >> 8), \
  (a[(n)+2] = (d) & 255)

#define GET(a,n) \
  (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2])

#define MAX_PATTERN_SIZE (1 << 24)


#elif LINK_SIZE == 4

#define PUT(a,n,d)        \
  (a[n] = (d) >> 24),     \
  (a[(n)+1] = (d) >> 16), \
  (a[(n)+2] = (d) >> 8),  \
  (a[(n)+3] = (d) & 255)

#define GET(a,n) \
  (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3])

/* Keep it positive */
#define MAX_PATTERN_SIZE (1 << 30)

#else
#error LINK_SIZE must be either 2, 3, or 4
#endif

#else /* COMPILE_PCRE8 */

#ifdef COMPILE_PCRE16

#if LINK_SIZE == 2

#undef LINK_SIZE
#define LINK_SIZE 1

#define PUT(a,n,d)   \
  (a[n] = (d))

#define GET(a,n) \
  (a[n])

#define MAX_PATTERN_SIZE (1 << 16)

#elif LINK_SIZE == 3 || LINK_SIZE == 4

#undef LINK_SIZE
#define LINK_SIZE 2

#define PUT(a,n,d)   \
  (a[n] = (d) >> 16), \
  (a[(n)+1] = (d) & 65535)

#define GET(a,n) \
  (((a)[n] << 16) | (a)[(n)+1])

/* Keep it positive */
#define MAX_PATTERN_SIZE (1 << 30)

#else
#error LINK_SIZE must be either 2, 3, or 4
#endif

#else
#error Unsupported compiling mode
#endif /* COMPILE_PCRE16 */

#endif /* COMPILE_PCRE8 */

/* Convenience macro defined in terms of the others */

#define PUTINC(a,n,d)   PUT(a,n,d), a += LINK_SIZE


/* PCRE uses some other 2-byte quantities that do not change when the size of
offsets changes. There are used for repeat counts and for other things such as
capturing parenthesis numbers in back references. */

#ifdef COMPILE_PCRE8

#define IMM2_SIZE 2

#define PUT2(a,n,d)   \
  a[n] = (d) >> 8; \
  a[(n)+1] = (d) & 255

#define GET2(a,n) \
  (((a)[n] << 8) | (a)[(n)+1])

#else /* COMPILE_PCRE8 */

#ifdef COMPILE_PCRE16

#define IMM2_SIZE 1

#define PUT2(a,n,d)   \
   a[n] = d

#define GET2(a,n) \
   a[n]

#else
#error Unsupported compiling mode
#endif /* COMPILE_PCRE16 */

#endif /* COMPILE_PCRE8 */

#define PUT2INC(a,n,d)  PUT2(a,n,d), a += IMM2_SIZE

/* The maximum length of a MARK name is currently one data unit; it may be
changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */

#define MAX_MARK ((1 << (sizeof(pcre_uchar)*8)) - 1)

/* When UTF encoding is being used, a character is no longer just a single
character. The macros for character handling generate simple sequences when
used in character-mode, and more complicated ones for UTF characters.
GETCHARLENTEST and other macros are not used when UTF is not supported,
so they are not defined. To make sure they can never even appear when
UTF support is omitted, we don't even define them. */

#ifndef SUPPORT_UTF

/* #define MAX_VALUE_FOR_SINGLE_CHAR */
/* #define HAS_EXTRALEN(c) */
/* #define GET_EXTRALEN(c) */
/* #define NOT_FIRSTCHAR(c) */
#define GETCHAR(c, eptr) c = *eptr;
#define GETCHARTEST(c, eptr) c = *eptr;
#define GETCHARINC(c, eptr) c = *eptr++;
#define GETCHARINCTEST(c, eptr) c = *eptr++;
#define GETCHARLEN(c, eptr, len) c = *eptr;
/* #define GETCHARLENTEST(c, eptr, len) */
/* #define BACKCHAR(eptr) */
/* #define FORWARDCHAR(eptr) */
/* #define ACROSSCHAR(condition, eptr, action) */

#else   /* SUPPORT_UTF */

#ifdef COMPILE_PCRE8

/* These macros were originally written in the form of loops that used data
from the tables whose names start with PRIV(utf8_table). They were rewritten by
a user so as not to use loops, because in some environments this gives a
significant performance advantage, and it seems never to do any harm. */

/* Tells the biggest code point which can be encoded as a single character. */

#define MAX_VALUE_FOR_SINGLE_CHAR 127

/* Tests whether the code point needs extra characters to decode. */

#define HAS_EXTRALEN(c) ((c) >= 0xc0)

/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
Otherwise it has an undefined behaviour. */

#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3f])

/* Returns TRUE, if the given character is not the first character
of a UTF sequence. */

#define NOT_FIRSTCHAR(c) (((c) & 0xc0) == 0x80)

/* Base macro to pick up the remaining bytes of a UTF-8 character, not
advancing the pointer. */

#define GETUTF8(c, eptr) \
    { \
    if ((c & 0x20) == 0) \
      c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \
    else if ((c & 0x10) == 0) \
      c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
    else if ((c & 0x08) == 0) \
      c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \
      ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \
    else if ((c & 0x04) == 0) \
      c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \
          ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \
          (eptr[4] & 0x3f); \
    else \
      c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \
          ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \
          ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \
    }

/* Get the next UTF-8 character, not advancing the pointer. This is called when
we know we are in UTF-8 mode. */

#define GETCHAR(c, eptr) \
  c = *eptr; \
  if (c >= 0xc0) GETUTF8(c, eptr);

/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the
pointer. */

#define GETCHARTEST(c, eptr) \
  c = *eptr; \
  if (utf && c >= 0xc0) GETUTF8(c, eptr);

/* Base macro to pick up the remaining bytes of a UTF-8 character, advancing
the pointer. */

#define GETUTF8INC(c, eptr) \
    { \
    if ((c & 0x20) == 0) \
      c = ((c & 0x1f) << 6) | (*eptr++ & 0x3f); \
    else if ((c & 0x10) == 0) \
      { \
      c = ((c & 0x0f) << 12) | ((*eptr & 0x3f) << 6) | (eptr[1] & 0x3f); \
      eptr += 2; \
      } \
    else if ((c & 0x08) == 0) \
      { \
      c = ((c & 0x07) << 18) | ((*eptr & 0x3f) << 12) | \
          ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
      eptr += 3; \
      } \
    else if ((c & 0x04) == 0) \
      { \
      c = ((c & 0x03) << 24) | ((*eptr & 0x3f) << 18) | \
          ((eptr[1] & 0x3f) << 12) | ((eptr[2] & 0x3f) << 6) | \
          (eptr[3] & 0x3f); \
      eptr += 4; \
      } \
    else \
      { \
      c = ((c & 0x01) << 30) | ((*eptr & 0x3f) << 24) | \
          ((eptr[1] & 0x3f) << 18) | ((eptr[2] & 0x3f) << 12) | \
          ((eptr[3] & 0x3f) << 6) | (eptr[4] & 0x3f); \
      eptr += 5; \
      } \
    }

/* Get the next UTF-8 character, advancing the pointer. This is called when we
know we are in UTF-8 mode. */

#define GETCHARINC(c, eptr) \
  c = *eptr++; \
  if (c >= 0xc0) GETUTF8INC(c, eptr);

/* Get the next character, testing for UTF-8 mode, and advancing the pointer.
This is called when we don't know if we are in UTF-8 mode. */

#define GETCHARINCTEST(c, eptr) \
  c = *eptr++; \
  if (utf && c >= 0xc0) GETUTF8INC(c, eptr);

/* Base macro to pick up the remaining bytes of a UTF-8 character, not
advancing the pointer, incrementing the length. */

#define GETUTF8LEN(c, eptr, len) \
    { \
    if ((c & 0x20) == 0) \
      { \
      c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \
      len++; \
      } \
    else if ((c & 0x10)  == 0) \
      { \
      c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
      len += 2; \
      } \
    else if ((c & 0x08)  == 0) \
      {\
      c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \
          ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \
      len += 3; \
      } \
    else if ((c & 0x04)  == 0) \
      { \
      c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \
          ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \
          (eptr[4] & 0x3f); \
      len += 4; \
      } \
    else \
      {\
      c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \
          ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \
          ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \
      len += 5; \
      } \
    }

/* Get the next UTF-8 character, not advancing the pointer, incrementing length
if there are extra bytes. This is called when we know we are in UTF-8 mode. */

#define GETCHARLEN(c, eptr, len) \
  c = *eptr; \
  if (c >= 0xc0) GETUTF8LEN(c, eptr, len);

/* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the
pointer, incrementing length if there are extra bytes. This is called when we
do not know if we are in UTF-8 mode. */

#define GETCHARLENTEST(c, eptr, len) \
  c = *eptr; \
  if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len);

/* If the pointer is not at the start of a character, move it back until
it is. This is called only in UTF-8 mode - we don't put a test within the macro
because almost all calls are already within a block of UTF-8 only code. */

#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--

/* Same as above, just in the other direction. */
#define FORWARDCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr++

/* Same as above, but it allows a fully customizable form. */
#define ACROSSCHAR(condition, eptr, action) \
  while((condition) && ((eptr) & 0xc0) == 0x80) action

#else /* COMPILE_PCRE8 */

#ifdef COMPILE_PCRE16

/* Tells the biggest code point which can be encoded as a single character. */

#define MAX_VALUE_FOR_SINGLE_CHAR 65535

/* Tests whether the code point needs extra characters to decode. */

#define HAS_EXTRALEN(c) (((c) & 0xfc00) == 0xd800)

/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
Otherwise it has an undefined behaviour. */

#define GET_EXTRALEN(c) 1

/* Returns TRUE, if the given character is not the first character
of a UTF sequence. */

#define NOT_FIRSTCHAR(c) (((c) & 0xfc00) == 0xdc00)

/* Base macro to pick up the low surrogate of a UTF-16 character, not
advancing the pointer. */

#define GETUTF16(c, eptr) \
   { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; }

/* Get the next UTF-16 character, not advancing the pointer. This is called when
we know we are in UTF-16 mode. */

#define GETCHAR(c, eptr) \
  c = *eptr; \
  if ((c & 0xfc00) == 0xd800) GETUTF16(c, eptr);

/* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the
pointer. */

#define GETCHARTEST(c, eptr) \
  c = *eptr; \
  if (utf && (c & 0xfc00) == 0xd800) GETUTF16(c, eptr);

/* Base macro to pick up the low surrogate of a UTF-16 character, advancing
the pointer. */

#define GETUTF16INC(c, eptr) \
   { c = (((c & 0x3ff) << 10) | (*eptr++ & 0x3ff)) + 0x10000; }

/* Get the next UTF-16 character, advancing the pointer. This is called when we
know we are in UTF-16 mode. */

#define GETCHARINC(c, eptr) \
  c = *eptr++; \
  if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr);

/* Get the next character, testing for UTF-16 mode, and advancing the pointer.
This is called when we don't know if we are in UTF-16 mode. */

#define GETCHARINCTEST(c, eptr) \
  c = *eptr++; \
  if (utf && (c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr);

/* Base macro to pick up the low surrogate of a UTF-16 character, not
advancing the pointer, incrementing the length. */

#define GETUTF16LEN(c, eptr, len) \
   { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; len++; }

/* Get the next UTF-16 character, not advancing the pointer, incrementing
length if there is a low surrogate. This is called when we know we are in
UTF-16 mode. */

#define GETCHARLEN(c, eptr, len) \
  c = *eptr; \
  if ((c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len);

/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the
pointer, incrementing length if there is a low surrogate. This is called when
we do not know if we are in UTF-16 mode. */

#define GETCHARLENTEST(c, eptr, len) \
  c = *eptr; \
  if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len);

/* If the pointer is not at the start of a character, move it back until
it is. This is called only in UTF-16 mode - we don't put a test within the
macro because almost all calls are already within a block of UTF-16 only
code. */

#define BACKCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr--

/* Same as above, just in the other direction. */
#define FORWARDCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr++

/* Same as above, but it allows a fully customizable form. */
#define ACROSSCHAR(condition, eptr, action) \
  if ((condition) && ((eptr) & 0xfc00) == 0xdc00) action

#endif

#endif /* COMPILE_PCRE8 */

#endif  /* SUPPORT_UTF */


/* In case there is no definition of offsetof() provided - though any proper
Standard C system should have one. */

#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif


/* Private flags containing information about the compiled regex. They used to
live at the top end of the options word, but that got almost full, so now they
are in a 16-bit flags word. From release 8.00, PCRE_NOPARTIAL is unused, as
the restrictions on partial matching have been lifted. It remains for backwards
compatibility. */

#ifdef COMPILE_PCRE8
#define PCRE_MODE          0x0001  /* compiled in 8 bit mode */
#endif
#ifdef COMPILE_PCRE16
#define PCRE_MODE          0x0002  /* compiled in 16 bit mode */
#endif
#define PCRE_FIRSTSET      0x0010  /* first_char is set */
#define PCRE_FCH_CASELESS  0x0020  /* caseless first char */
#define PCRE_REQCHSET      0x0040  /* req_byte is set */
#define PCRE_RCH_CASELESS  0x0080  /* caseless requested char */
#define PCRE_STARTLINE     0x0100  /* start after \n for multiline */
#define PCRE_NOPARTIAL     0x0200  /* can't use partial with this regex */
#define PCRE_JCHANGED      0x0400  /* j option used in regex */
#define PCRE_HASCRORLF     0x0800  /* explicit \r or \n in pattern */
#define PCRE_HASTHEN       0x1000  /* pattern contains (*THEN) */

/* Flags for the "extra" block produced by STUDY8(). */

#define PCRE_STUDY_MAPPED  0x0001  /* a map of starting chars exists */
#define PCRE_STUDY_MINLEN  0x0002  /* a minimum length field exists */

/* Masks for identifying the public options that are permitted at compile
time, run time, or study time, respectively. */

#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \
                           PCRE_NEWLINE_ANYCRLF)

#define PUBLIC_COMPILE_OPTIONS \
  (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
   PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \
   PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \
   PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \
   PCRE_JAVASCRIPT_COMPAT|PCRE_UCP|PCRE_NO_START_OPTIMIZE)

#define PUBLIC_EXEC_OPTIONS \
  (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \
   PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_NEWLINE_BITS| \
   PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE|PCRE_NO_START_OPTIMIZE)

#define PUBLIC_DFA_EXEC_OPTIONS \
  (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \
   PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_SHORTEST| \
   PCRE_DFA_RESTART|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \
   PCRE_NO_START_OPTIMIZE)

#define PUBLIC_STUDY_OPTIONS \
   (PCRE_STUDY_JIT_COMPILE|PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE| \
    PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE)

/* Magic number to provide a small check against being handed junk. */

#define MAGIC_NUMBER  0x50435245UL   /* 'PCRE' */

/* This variable is used to detect a loaded regular expression
in different endianness. */

#define REVERSED_MAGIC_NUMBER  0x45524350UL   /* 'ERCP' */

/* Negative values for the firstchar and reqchar variables */

#define REQ_UNSET (-2)
#define REQ_NONE  (-1)

/* The maximum remaining length of subject we are prepared to search for a
req_byte match. */

#define REQ_BYTE_MAX 1000

/* Miscellaneous definitions. The #ifndef is to pacify compiler warnings in
environments where these macros are defined elsewhere. Unfortunately, there
is no way to do the same for the typedef. */

typedef int BOOL;

#ifndef FALSE
#define FALSE   0
#define TRUE    1
#endif

/* If PCRE is to support UTF-8 on EBCDIC platforms, we cannot use normal
character constants like '*' because the compiler would emit their EBCDIC code,
which is different from their ASCII/UTF-8 code. Instead we define macros for
the characters so that they always use the ASCII/UTF-8 code when UTF-8 support
is enabled. When UTF-8 support is not enabled, the definitions use character
literals. Both character and string versions of each character are needed, and
there are some longer strings as well.

This means that, on EBCDIC platforms, the PCRE library can handle either
EBCDIC, or UTF-8, but not both. To support both in the same compiled library
would need different lookups depending on whether PCRE_UTF8 was set or not.
This would make it impossible to use characters in switch/case statements,
which would reduce performance. For a theoretical use (which nobody has asked
for) in a minority area (EBCDIC platforms), this is not sensible. Any
application that did need both could compile two versions of the library, using
macros to give the functions distinct names. */

#ifndef SUPPORT_UTF

/* UTF-8 support is not enabled; use the platform-dependent character literals
so that PCRE works on both ASCII and EBCDIC platforms, in non-UTF-mode only. */

#define CHAR_HT                     '\t'
#define CHAR_VT                     '\v'
#define CHAR_FF                     '\f'
#define CHAR_CR                     '\r'
#define CHAR_NL                     '\n'
#define CHAR_BS                     '\b'
#define CHAR_BEL                    '\a'
#ifdef EBCDIC
#define CHAR_ESC                    '\047'
#define CHAR_DEL                    '\007'
#else
#define CHAR_ESC                    '\033'
#define CHAR_DEL                    '\177'
#endif

#define CHAR_SPACE                  ' '
#define CHAR_EXCLAMATION_MARK       '!'
#define CHAR_QUOTATION_MARK         '"'
#define CHAR_NUMBER_SIGN            '#'
#define CHAR_DOLLAR_SIGN            '$'
#define CHAR_PERCENT_SIGN           '%'
#define CHAR_AMPERSAND              '&'
#define CHAR_APOSTROPHE             '\''
#define CHAR_LEFT_PARENTHESIS       '('
#define CHAR_RIGHT_PARENTHESIS      ')'
#define CHAR_ASTERISK               '*'
#define CHAR_PLUS                   '+'
#define CHAR_COMMA                  ','
#define CHAR_MINUS                  '-'
#define CHAR_DOT                    '.'
#define CHAR_SLASH                  '/'
#define CHAR_0                      '0'
#define CHAR_1                      '1'
#define CHAR_2                      '2'
#define CHAR_3                      '3'
#define CHAR_4                      '4'
#define CHAR_5                      '5'
#define CHAR_6                      '6'
#define CHAR_7                      '7'
#define CHAR_8                      '8'
#define CHAR_9                      '9'
#define CHAR_COLON                  ':'
#define CHAR_SEMICOLON              ';'
#define CHAR_LESS_THAN_SIGN         '<'
#define CHAR_EQUALS_SIGN            '='
#define CHAR_GREATER_THAN_SIGN      '>'
#define CHAR_QUESTION_MARK          '?'
#define CHAR_COMMERCIAL_AT          '@'
#define CHAR_A                      'A'
#define CHAR_B                      'B'
#define CHAR_C                      'C'
#define CHAR_D                      'D'
#define CHAR_E                      'E'
#define CHAR_F                      'F'
#define CHAR_G                      'G'
#define CHAR_H                      'H'
#define CHAR_I                      'I'
#define CHAR_J                      'J'
#define CHAR_K                      'K'
#define CHAR_L                      'L'
#define CHAR_M                      'M'
#define CHAR_N                      'N'
#define CHAR_O                      'O'
#define CHAR_P                      'P'
#define CHAR_Q                      'Q'
#define CHAR_R                      'R'
#define CHAR_S                      'S'
#define CHAR_T                      'T'
#define CHAR_U                      'U'
#define CHAR_V                      'V'
#define CHAR_W                      'W'
#define CHAR_X                      'X'
#define CHAR_Y                      'Y'
#define CHAR_Z                      'Z'
#define CHAR_LEFT_SQUARE_BRACKET    '['
#define CHAR_BACKSLASH              '\\'
#define CHAR_RIGHT_SQUARE_BRACKET   ']'
#define CHAR_CIRCUMFLEX_ACCENT      ''
#define CHAR_UNDERSCORE             '_'
#define CHAR_GRAVE_ACCENT           '`'
#define CHAR_a                      'a'
#define CHAR_b                      'b'
#define CHAR_c                      'c'
#define CHAR_d                      'd'
#define CHAR_e                      'e'
#define CHAR_f                      'f'
#define CHAR_g                      'g'
#define CHAR_h                      'h'
#define CHAR_i                      'i'
#define CHAR_j                      'j'
#define CHAR_k                      'k'
#define CHAR_l                      'l'
#define CHAR_m                      'm'
#define CHAR_n                      'n'
#define CHAR_o                      'o'
#define CHAR_p                      'p'
#define CHAR_q                      'q'
#define CHAR_r                      'r'
#define CHAR_s                      's'
#define CHAR_t                      't'
#define CHAR_u                      'u'
#define CHAR_v                      'v'
#define CHAR_w                      'w'
#define CHAR_x                      'x'
#define CHAR_y                      'y'
#define CHAR_z                      'z'
#define CHAR_LEFT_CURLY_BRACKET     '{'
#define CHAR_VERTICAL_LINE          '|'
#define CHAR_RIGHT_CURLY_BRACKET    '}'
#define CHAR_TILDE                  '~'

#define STR_HT                      "\t"
#define STR_VT                      "\v"
#define STR_FF                      "\f"
#define STR_CR                      "\r"
#define STR_NL                      "\n"
#define STR_BS                      "\b"
#define STR_BEL                     "\a"
#ifdef EBCDIC
#define STR_ESC                     "\047"
#define STR_DEL                     "\007"
#else
#define STR_ESC                     "\033"
#define STR_DEL                     "\177"
#endif

#define STR_SPACE                   " "
#define STR_EXCLAMATION_MARK        "!"
#define STR_QUOTATION_MARK          "\""
#define STR_NUMBER_SIGN             "#"
#define STR_DOLLAR_SIGN             "$"
#define STR_PERCENT_SIGN            "%"
#define STR_AMPERSAND               "&"
#define STR_APOSTROPHE              "'"
#define STR_LEFT_PARENTHESIS        "("
#define STR_RIGHT_PARENTHESIS       ")"
#define STR_ASTERISK                "*"
#define STR_PLUS                    "+"
#define STR_COMMA                   ","
#define STR_MINUS                   "-"
#define STR_DOT                     "."
#define STR_SLASH                   "/"
#define STR_0                       "0"
#define STR_1                       "1"
#define STR_2                       "2"
#define STR_3                       "3"
#define STR_4                       "4"
#define STR_5                       "5"
#define STR_6                       "6"
#define STR_7                       "7"
#define STR_8                       "8"
#define STR_9                       "9"
#define STR_COLON                   ":"
#define STR_SEMICOLON               ";"
#define STR_LESS_THAN_SIGN          "<"
#define STR_EQUALS_SIGN             "="
#define STR_GREATER_THAN_SIGN       ">"
#define STR_QUESTION_MARK           "?"
#define STR_COMMERCIAL_AT           "@"
#define STR_A                       "A"
#define STR_B                       "B"
#define STR_C                       "C"
#define STR_D                       "D"
#define STR_E                       "E"
#define STR_F                       "F"
#define STR_G                       "G"
#define STR_H                       "H"
#define STR_I                       "I"
#define STR_J                       "J"
#define STR_K                       "K"
#define STR_L                       "L"
#define STR_M                       "M"
#define STR_N                       "N"
#define STR_O                       "O"
#define STR_P                       "P"
#define STR_Q                       "Q"
#define STR_R                       "R"
#define STR_S                       "S"
#define STR_T                       "T"
#define STR_U                       "U"
#define STR_V                       "V"
#define STR_W                       "W"
#define STR_X                       "X"
#define STR_Y                       "Y"
#define STR_Z                       "Z"
#define STR_LEFT_SQUARE_BRACKET     "["
#define STR_BACKSLASH               "\\"
#define STR_RIGHT_SQUARE_BRACKET    "]"
#define STR_CIRCUMFLEX_ACCENT       ""
#define STR_UNDERSCORE              "_"
#define STR_GRAVE_ACCENT            "`"
#define STR_a                       "a"
#define STR_b                       "b"
#define STR_c                       "c"
#define STR_d                       "d"
#define STR_e                       "e"
#define STR_f                       "f"
#define STR_g                       "g"
#define STR_h                       "h"
#define STR_i                       "i"
#define STR_j                       "j"
#define STR_k                       "k"
#define STR_l                       "l"
#define STR_m                       "m"
#define STR_n                       "n"
#define STR_o                       "o"
#define STR_p                       "p"
#define STR_q                       "q"
#define STR_r                       "r"
#define STR_s                       "s"
#define STR_t                       "t"
#define STR_u                       "u"
#define STR_v                       "v"
#define STR_w                       "w"
#define STR_x                       "x"
#define STR_y                       "y"
#define STR_z                       "z"
#define STR_LEFT_CURLY_BRACKET      "{"
#define STR_VERTICAL_LINE           "|"
#define STR_RIGHT_CURLY_BRACKET     "}"
#define STR_TILDE                   "~"

#define STRING_ACCEPT0              "ACCEPT\0"
#define STRING_COMMIT0              "COMMIT\0"
#define STRING_F0                   "F\0"
#define STRING_FAIL0                "FAIL\0"
#define STRING_MARK0                "MARK\0"
#define STRING_PRUNE0               "PRUNE\0"
#define STRING_SKIP0                "SKIP\0"
#define STRING_THEN                 "THEN"

#define STRING_alpha0               "alpha\0"
#define STRING_lower0               "lower\0"
#define STRING_upper0               "upper\0"
#define STRING_alnum0               "alnum\0"
#define STRING_ascii0               "ascii\0"
#define STRING_blank0               "blank\0"
#define STRING_cntrl0               "cntrl\0"
#define STRING_digit0               "digit\0"
#define STRING_graph0               "graph\0"
#define STRING_print0               "print\0"
#define STRING_punct0               "punct\0"
#define STRING_space0               "space\0"
#define STRING_word0                "word\0"
#define STRING_xdigit               "xdigit"

#define STRING_DEFINE               "DEFINE"

#define STRING_CR_RIGHTPAR             "CR)"
#define STRING_LF_RIGHTPAR             "LF)"
#define STRING_CRLF_RIGHTPAR           "CRLF)"
#define STRING_ANY_RIGHTPAR            "ANY)"
#define STRING_ANYCRLF_RIGHTPAR        "ANYCRLF)"
#define STRING_BSR_ANYCRLF_RIGHTPAR    "BSR_ANYCRLF)"
#define STRING_BSR_UNICODE_RIGHTPAR    "BSR_UNICODE)"
#ifdef COMPILE_PCRE8
#define STRING_UTF_RIGHTPAR            "UTF8)"
#endif
#ifdef COMPILE_PCRE16
#define STRING_UTF_RIGHTPAR            "UTF16)"
#endif
#define STRING_UCP_RIGHTPAR            "UCP)"
#define STRING_NO_START_OPT_RIGHTPAR   "NO_START_OPT)"

#else  /* SUPPORT_UTF */

/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This
works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode
only. */

#define CHAR_HT                     '\011'
#define CHAR_VT                     '\013'
#define CHAR_FF                     '\014'
#define CHAR_CR                     '\015'
#define CHAR_NL                     '\012'
#define CHAR_BS                     '\010'
#define CHAR_BEL                    '\007'
#define CHAR_ESC                    '\033'
#define CHAR_DEL                    '\177'

#define CHAR_SPACE                  '\040'
#define CHAR_EXCLAMATION_MARK       '\041'
#define CHAR_QUOTATION_MARK         '\042'
#define CHAR_NUMBER_SIGN            '\043'
#define CHAR_DOLLAR_SIGN            '\044'
#define CHAR_PERCENT_SIGN           '\045'
#define CHAR_AMPERSAND              '\046'
#define CHAR_APOSTROPHE             '\047'
#define CHAR_LEFT_PARENTHESIS       '\050'
#define CHAR_RIGHT_PARENTHESIS      '\051'
#define CHAR_ASTERISK               '\052'
#define CHAR_PLUS                   '\053'
#define CHAR_COMMA                  '\054'
#define CHAR_MINUS                  '\055'
#define CHAR_DOT                    '\056'
#define CHAR_SLASH                  '\057'
#define CHAR_0                      '\060'
#define CHAR_1                      '\061'
#define CHAR_2                      '\062'
#define CHAR_3                      '\063'
#define CHAR_4                      '\064'
#define CHAR_5                      '\065'
#define CHAR_6                      '\066'
#define CHAR_7                      '\067'
#define CHAR_8                      '\070'
#define CHAR_9                      '\071'
#define CHAR_COLON                  '\072'
#define CHAR_SEMICOLON              '\073'
#define CHAR_LESS_THAN_SIGN         '\074'
#define CHAR_EQUALS_SIGN            '\075'
#define CHAR_GREATER_THAN_SIGN      '\076'
#define CHAR_QUESTION_MARK          '\077'
#define CHAR_COMMERCIAL_AT          '\100'
#define CHAR_A                      '\101'
#define CHAR_B                      '\102'
#define CHAR_C                      '\103'
#define CHAR_D                      '\104'
#define CHAR_E                      '\105'
#define CHAR_F                      '\106'
#define CHAR_G                      '\107'
#define CHAR_H                      '\110'
#define CHAR_I                      '\111'
#define CHAR_J                      '\112'
#define CHAR_K                      '\113'
#define CHAR_L                      '\114'
#define CHAR_M                      '\115'
#define CHAR_N                      '\116'
#define CHAR_O                      '\117'
#define CHAR_P                      '\120'
#define CHAR_Q                      '\121'
#define CHAR_R                      '\122'
#define CHAR_S                      '\123'
#define CHAR_T                      '\124'
#define CHAR_U                      '\125'
#define CHAR_V                      '\126'
#define CHAR_W                      '\127'
#define CHAR_X                      '\130'
#define CHAR_Y                      '\131'
#define CHAR_Z                      '\132'
#define CHAR_LEFT_SQUARE_BRACKET    '\133'
#define CHAR_BACKSLASH              '\134'
#define CHAR_RIGHT_SQUARE_BRACKET   '\135'
#define CHAR_CIRCUMFLEX_ACCENT      '\136'
#define CHAR_UNDERSCORE             '\137'
#define CHAR_GRAVE_ACCENT           '\140'
#define CHAR_a                      '\141'
#define CHAR_b                      '\142'
#define CHAR_c                      '\143'
#define CHAR_d                      '\144'
#define CHAR_e                      '\145'
#define CHAR_f                      '\146'
#define CHAR_g                      '\147'
#define CHAR_h                      '\150'
#define CHAR_i                      '\151'
#define CHAR_j                      '\152'
#define CHAR_k                      '\153'
#define CHAR_l                      '\154'
#define CHAR_m                      '\155'
#define CHAR_n                      '\156'
#define CHAR_o                      '\157'
#define CHAR_p                      '\160'
#define CHAR_q                      '\161'
#define CHAR_r                      '\162'
#define CHAR_s                      '\163'
#define CHAR_t                      '\164'
#define CHAR_u                      '\165'
#define CHAR_v                      '\166'
#define CHAR_w                      '\167'
#define CHAR_x                      '\170'
#define CHAR_y                      '\171'
#define CHAR_z                      '\172'
#define CHAR_LEFT_CURLY_BRACKET     '\173'
#define CHAR_VERTICAL_LINE          '\174'
#define CHAR_RIGHT_CURLY_BRACKET    '\175'
#define CHAR_TILDE                  '\176'

#define STR_HT                      "\011"
#define STR_VT                      "\013"
#define STR_FF                      "\014"
#define STR_CR                      "\015"
#define STR_NL                      "\012"
#define STR_BS                      "\010"
#define STR_BEL                     "\007"
#define STR_ESC                     "\033"
#define STR_DEL                     "\177"

#define STR_SPACE                   "\040"
#define STR_EXCLAMATION_MARK        "\041"
#define STR_QUOTATION_MARK          "\042"
#define STR_NUMBER_SIGN             "\043"
#define STR_DOLLAR_SIGN             "\044"
#define STR_PERCENT_SIGN            "\045"
#define STR_AMPERSAND               "\046"
#define STR_APOSTROPHE              "\047"
#define STR_LEFT_PARENTHESIS        "\050"
#define STR_RIGHT_PARENTHESIS       "\051"
#define STR_ASTERISK                "\052"
#define STR_PLUS                    "\053"
#define STR_COMMA                   "\054"
#define STR_MINUS                   "\055"
#define STR_DOT                     "\056"
#define STR_SLASH                   "\057"
#define STR_0                       "\060"
#define STR_1                       "\061"
#define STR_2                       "\062"
#define STR_3                       "\063"
#define STR_4                       "\064"
#define STR_5                       "\065"
#define STR_6                       "\066"
#define STR_7                       "\067"
#define STR_8                       "\070"
#define STR_9                       "\071"
#define STR_COLON                   "\072"
#define STR_SEMICOLON               "\073"
#define STR_LESS_THAN_SIGN          "\074"
#define STR_EQUALS_SIGN             "\075"
#define STR_GREATER_THAN_SIGN       "\076"
#define STR_QUESTION_MARK           "\077"
#define STR_COMMERCIAL_AT           "\100"
#define STR_A                       "\101"
#define STR_B                       "\102"
#define STR_C                       "\103"
#define STR_D                       "\104"
#define STR_E                       "\105"
#define STR_F                       "\106"
#define STR_G                       "\107"
#define STR_H                       "\110"
#define STR_I                       "\111"
#define STR_J                       "\112"
#define STR_K                       "\113"
#define STR_L                       "\114"
#define STR_M                       "\115"
#define STR_N                       "\116"
#define STR_O                       "\117"
#define STR_P                       "\120"
#define STR_Q                       "\121"
#define STR_R                       "\122"
#define STR_S                       "\123"
#define STR_T                       "\124"
#define STR_U                       "\125"
#define STR_V                       "\126"
#define STR_W                       "\127"
#define STR_X                       "\130"
#define STR_Y                       "\131"
#define STR_Z                       "\132"
#define STR_LEFT_SQUARE_BRACKET     "\133"
#define STR_BACKSLASH               "\134"
#define STR_RIGHT_SQUARE_BRACKET    "\135"
#define STR_CIRCUMFLEX_ACCENT       "\136"
#define STR_UNDERSCORE              "\137"
#define STR_GRAVE_ACCENT            "\140"
#define STR_a                       "\141"
#define STR_b                       "\142"
#define STR_c                       "\143"
#define STR_d                       "\144"
#define STR_e                       "\145"
#define STR_f                       "\146"
#define STR_g                       "\147"
#define STR_h                       "\150"
#define STR_i                       "\151"
#define STR_j                       "\152"
#define STR_k                       "\153"
#define STR_l                       "\154"
#define STR_m                       "\155"
#define STR_n                       "\156"
#define STR_o                       "\157"
#define STR_p                       "\160"
#define STR_q                       "\161"
#define STR_r                       "\162"
#define STR_s                       "\163"
#define STR_t                       "\164"
#define STR_u                       "\165"
#define STR_v                       "\166"
#define STR_w                       "\167"
#define STR_x                       "\170"
#define STR_y                       "\171"
#define STR_z                       "\172"
#define STR_LEFT_CURLY_BRACKET      "\173"
#define STR_VERTICAL_LINE           "\174"
#define STR_RIGHT_CURLY_BRACKET     "\175"
#define STR_TILDE                   "\176"

#define STRING_ACCEPT0              STR_A STR_C STR_C STR_E STR_P STR_T "\0"
#define STRING_COMMIT0              STR_C STR_O STR_M STR_M STR_I STR_T "\0"
#define STRING_F0                   STR_F "\0"
#define STRING_FAIL0                STR_F STR_A STR_I STR_L "\0"
#define STRING_MARK0                STR_M STR_A STR_R STR_K "\0"
#define STRING_PRUNE0               STR_P STR_R STR_U STR_N STR_E "\0"
#define STRING_SKIP0                STR_S STR_K STR_I STR_P "\0"
#define STRING_THEN                 STR_T STR_H STR_E STR_N

#define STRING_alpha0               STR_a STR_l STR_p STR_h STR_a "\0"
#define STRING_lower0               STR_l STR_o STR_w STR_e STR_r "\0"
#define STRING_upper0               STR_u STR_p STR_p STR_e STR_r "\0"
#define STRING_alnum0               STR_a STR_l STR_n STR_u STR_m "\0"
#define STRING_ascii0               STR_a STR_s STR_c STR_i STR_i "\0"
#define STRING_blank0               STR_b STR_l STR_a STR_n STR_k "\0"
#define STRING_cntrl0               STR_c STR_n STR_t STR_r STR_l "\0"
#define STRING_digit0               STR_d STR_i STR_g STR_i STR_t "\0"
#define STRING_graph0               STR_g STR_r STR_a STR_p STR_h "\0"
#define STRING_print0               STR_p STR_r STR_i STR_n STR_t "\0"
#define STRING_punct0               STR_p STR_u STR_n STR_c STR_t "\0"
#define STRING_space0               STR_s STR_p STR_a STR_c STR_e "\0"
#define STRING_word0                STR_w STR_o STR_r STR_d       "\0"
#define STRING_xdigit               STR_x STR_d STR_i STR_g STR_i STR_t

#define STRING_DEFINE               STR_D STR_E STR_F STR_I STR_N STR_E

#define STRING_CR_RIGHTPAR             STR_C STR_R STR_RIGHT_PARENTHESIS
#define STRING_LF_RIGHTPAR             STR_L STR_F STR_RIGHT_PARENTHESIS
#define STRING_CRLF_RIGHTPAR           STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
#define STRING_ANY_RIGHTPAR            STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS
#define STRING_ANYCRLF_RIGHTPAR        STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
#define STRING_BSR_ANYCRLF_RIGHTPAR    STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
#define STRING_BSR_UNICODE_RIGHTPAR    STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS
#ifdef COMPILE_PCRE8
#define STRING_UTF_RIGHTPAR            STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS
#endif
#ifdef COMPILE_PCRE16
#define STRING_UTF_RIGHTPAR            STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS
#endif
#define STRING_UCP_RIGHTPAR            STR_U STR_C STR_P STR_RIGHT_PARENTHESIS
#define STRING_NO_START_OPT_RIGHTPAR   STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS

#endif  /* SUPPORT_UTF */

/* Escape items that are just an encoding of a particular data value. */

#ifndef ESC_e
#define ESC_e CHAR_ESC
#endif

#ifndef ESC_f
#define ESC_f CHAR_FF
#endif

#ifndef ESC_n
#define ESC_n CHAR_NL
#endif

#ifndef ESC_r
#define ESC_r CHAR_CR
#endif

/* We can't officially use ESC_t because it is a POSIX reserved identifier
(presumably because of all the others like size_t). */

#ifndef ESC_tee
#define ESC_tee CHAR_HT
#endif

/* Codes for different types of Unicode property */

#define PT_ANY        0    /* Any property - matches all chars */
#define PT_LAMP       1    /* L& - the union of Lu, Ll, Lt */
#define PT_GC         2    /* Specified general characteristic (e.g. L) */
#define PT_PC         3    /* Specified particular characteristic (e.g. Lu) */
#define PT_SC         4    /* Script (e.g. Han) */
#define PT_ALNUM      5    /* Alphanumeric - the union of L and N */
#define PT_SPACE      6    /* Perl space - Z plus 9,10,12,13 */
#define PT_PXSPACE    7    /* POSIX space - Z plus 9,10,11,12,13 */
#define PT_WORD       8    /* Word - L plus N plus underscore */

/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
contain characters with values greater than 255. */

#define XCL_NOT    0x01    /* Flag: this is a negative class */
#define XCL_MAP    0x02    /* Flag: a 32-byte map is present */

#define XCL_END       0    /* Marks end of individual items */
#define XCL_SINGLE    1    /* Single item (one multibyte char) follows */
#define XCL_RANGE     2    /* A range (two multibyte chars) follows */
#define XCL_PROP      3    /* Unicode property (2-byte property code follows) */
#define XCL_NOTPROP   4    /* Unicode inverted property (ditto) */

/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns
their negation. Also, they must appear in the same order as in the opcode
definitions below, up to ESC_z. There's a dummy for OP_ALLANY because it
corresponds to "." in DOTALL mode rather than an escape sequence. It is also
used for [] in JavaScript compatibility mode, and for \C in non-utf mode. In
non-DOTALL mode, "." behaves like \N.

The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc.
when PCRE_UCP is set, when replacement of \d etc by \p sequences is required.
They must be contiguous, and remain in order so that the replacements can be
looked up from a table.

The final escape must be ESC_REF as subsequent values are used for
backreferences (\1, \2, \3, etc). There are two tests in the code for an escape
greater than ESC_b and less than ESC_Z to detect the types that may be
repeated. These are the types that consume characters. If any new escapes are
put in between that don't consume a character, that code will have to change.
*/

enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
       ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,
       ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z,
       ESC_E, ESC_Q, ESC_g, ESC_k,
       ESC_DU, ESC_du, ESC_SU, ESC_su, ESC_WU, ESC_wu,
       ESC_REF };

/* Opcode table: Starting from 1 (i.e. after OP_END), the values up to
OP_EOD must correspond in order to the list of escapes immediately above.

*** NOTE NOTE NOTE *** Whenever this list is updated, the two macro definitions
that follow must also be updated to match. There are also tables called
"coptable" and "poptable" in DFAEXEC8.c that must be updated. */

enum {
  OP_END,            /* 0 End of pattern */

  /* Values corresponding to backslashed metacharacters */

  OP_SOD,            /* 1 Start of data: \A */
  OP_SOM,            /* 2 Start of match (subject + offset): \G */
  OP_SET_SOM,        /* 3 Set start of match (\K) */
  OP_NOT_WORD_BOUNDARY,  /*  4 \B */
  OP_WORD_BOUNDARY,      /*  5 \b */
  OP_NOT_DIGIT,          /*  6 \D */
  OP_DIGIT,              /*  7 \d */
  OP_NOT_WHITESPACE,     /*  8 \S */
  OP_WHITESPACE,         /*  9 \s */
  OP_NOT_WORDCHAR,       /* 10 \W */
  OP_WORDCHAR,           /* 11 \w */

  OP_ANY,            /* 12 Match any character except newline */
  OP_ALLANY,         /* 13 Match any character */
  OP_ANYBYTE,        /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */
  OP_NOTPROP,        /* 15 \P (not Unicode property) */
  OP_PROP,           /* 16 \p (Unicode property) */
  OP_ANYNL,          /* 17 \R (any newline sequence) */
  OP_NOT_HSPACE,     /* 18 \H (not horizontal whitespace) */
  OP_HSPACE,         /* 19 \h (horizontal whitespace) */
  OP_NOT_VSPACE,     /* 20 \V (not vertical whitespace) */
  OP_VSPACE,         /* 21 \v (vertical whitespace) */
  OP_EXTUNI,         /* 22 \X (extended Unicode sequence */
  OP_EODN,           /* 23 End of data or \n at end of data: \Z. */
  OP_EOD,            /* 24 End of data: \z */

  OP_CIRC,           /* 25 Start of line - not multiline */
  OP_CIRCM,          /* 26 Start of line - multiline */
  OP_DOLL,           /* 27 End of line - not multiline */
  OP_DOLLM,          /* 28 End of line - multiline */
  OP_CHAR,           /* 29 Match one character, casefully */
  OP_CHARI,          /* 30 Match one character, caselessly */
  OP_NOT,            /* 31 Match one character, not the given one, casefully */
  OP_NOTI,           /* 32 Match one character, not the given one, caselessly */

  /* The following sets of 13 opcodes must always be kept in step because
  the offset from the first one is used to generate the others. */

  /**** Single characters, caseful, must precede the caseless ones ****/

  OP_STAR,           /* 33 The maximizing and minimizing versions of */
  OP_MINSTAR,        /* 34 these six opcodes must come in pairs, with */
  OP_PLUS,           /* 35 the minimizing one second. */
  OP_MINPLUS,        /* 36 */
  OP_QUERY,          /* 37 */
  OP_MINQUERY,       /* 38 */

  OP_UPTO,           /* 39 From 0 to n matches of one character, caseful*/
  OP_MINUPTO,        /* 40 */
  OP_EXACT,          /* 41 Exactly n matches */

  OP_POSSTAR,        /* 42 Possessified star, caseful */
  OP_POSPLUS,        /* 43 Possessified plus, caseful */
  OP_POSQUERY,       /* 44 Posesssified query, caseful */
  OP_POSUPTO,        /* 45 Possessified upto, caseful */

  /**** Single characters, caseless, must follow the caseful ones */

  OP_STARI,          /* 46 */
  OP_MINSTARI,       /* 47 */
  OP_PLUSI,          /* 48 */
  OP_MINPLUSI,       /* 49 */
  OP_QUERYI,         /* 50 */
  OP_MINQUERYI,      /* 51 */

  OP_UPTOI,          /* 52 From 0 to n matches of one character, caseless */
  OP_MINUPTOI,       /* 53 */
  OP_EXACTI,         /* 54 */

  OP_POSSTARI,       /* 55 Possessified star, caseless */
  OP_POSPLUSI,       /* 56 Possessified plus, caseless */
  OP_POSQUERYI,      /* 57 Posesssified query, caseless */
  OP_POSUPTOI,       /* 58 Possessified upto, caseless */

  /**** The negated ones must follow the non-negated ones, and match them ****/
  /**** Negated single character, caseful; must precede the caseless ones ****/

  OP_NOTSTAR,        /* 59 The maximizing and minimizing versions of */
  OP_NOTMINSTAR,     /* 60 these six opcodes must come in pairs, with */
  OP_NOTPLUS,        /* 61 the minimizing one second. They must be in */
  OP_NOTMINPLUS,     /* 62 exactly the same order as those above. */
  OP_NOTQUERY,       /* 63 */
  OP_NOTMINQUERY,    /* 64 */

  OP_NOTUPTO,        /* 65 From 0 to n matches, caseful */
  OP_NOTMINUPTO,     /* 66 */
  OP_NOTEXACT,       /* 67 Exactly n matches */

  OP_NOTPOSSTAR,     /* 68 Possessified versions, caseful */
  OP_NOTPOSPLUS,     /* 69 */
  OP_NOTPOSQUERY,    /* 70 */
  OP_NOTPOSUPTO,     /* 71 */

  /**** Negated single character, caseless; must follow the caseful ones ****/

  OP_NOTSTARI,       /* 72 */
  OP_NOTMINSTARI,    /* 73 */
  OP_NOTPLUSI,       /* 74 */
  OP_NOTMINPLUSI,    /* 75 */
  OP_NOTQUERYI,      /* 76 */
  OP_NOTMINQUERYI,   /* 77 */

  OP_NOTUPTOI,       /* 78 From 0 to n matches, caseless */
  OP_NOTMINUPTOI,    /* 79 */
  OP_NOTEXACTI,      /* 80 Exactly n matches */

  OP_NOTPOSSTARI,    /* 81 Possessified versions, caseless */
  OP_NOTPOSPLUSI,    /* 82 */
  OP_NOTPOSQUERYI,   /* 83 */
  OP_NOTPOSUPTOI,    /* 84 */

  /**** Character types ****/

  OP_TYPESTAR,       /* 85 The maximizing and minimizing versions of */
  OP_TYPEMINSTAR,    /* 86 these six opcodes must come in pairs, with */
  OP_TYPEPLUS,       /* 87 the minimizing one second. These codes must */
  OP_TYPEMINPLUS,    /* 88 be in exactly the same order as those above. */
  OP_TYPEQUERY,      /* 89 */
  OP_TYPEMINQUERY,   /* 90 */

  OP_TYPEUPTO,       /* 91 From 0 to n matches */
  OP_TYPEMINUPTO,    /* 92 */
  OP_TYPEEXACT,      /* 93 Exactly n matches */

  OP_TYPEPOSSTAR,    /* 94 Possessified versions */
  OP_TYPEPOSPLUS,    /* 95 */
  OP_TYPEPOSQUERY,   /* 96 */
  OP_TYPEPOSUPTO,    /* 97 */

  /* These are used for character classes and back references; only the
  first six are the same as the sets above. */

  OP_CRSTAR,         /* 98 The maximizing and minimizing versions of */
  OP_CRMINSTAR,      /* 99 all these opcodes must come in pairs, with */
  OP_CRPLUS,         /* 100 the minimizing one second. These codes must */
  OP_CRMINPLUS,      /* 101 be in exactly the same order as those above. */
  OP_CRQUERY,        /* 102 */
  OP_CRMINQUERY,     /* 103 */

  OP_CRRANGE,        /* 104 These are different to the three sets above. */
  OP_CRMINRANGE,     /* 105 */

  /* End of quantifier opcodes */

  OP_CLASS,          /* 106 Match a character class, chars < 256 only */
  OP_NCLASS,         /* 107 Same, but the bitmap was created from a negative
                              class - the difference is relevant only when a
                              character > 255 is encountered. */
  OP_XCLASS,         /* 108 Extended class for handling > 255 chars within the
                              class. This does both positive and negative. */
  OP_REF,            /* 109 Match a back reference, casefully */
  OP_REFI,           /* 110 Match a back reference, caselessly */
  OP_RECURSE,        /* 111 Match a numbered subpattern (possibly recursive) */
  OP_CALLOUT,        /* 112 Call out to external function if provided */

  OP_ALT,            /* 113 Start of alternation */
  OP_KET,            /* 114 End of group that doesn't have an unbounded repeat */
  OP_KETRMAX,        /* 115 These two must remain together and in this */
  OP_KETRMIN,        /* 116 order. They are for groups the repeat for ever. */
  OP_KETRPOS,        /* 117 Possessive unlimited repeat. */

  /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four
  asserts must remain in order. */

  OP_REVERSE,        /* 118 Move pointer back - used in lookbehind assertions */
  OP_ASSERT,         /* 119 Positive lookahead */
  OP_ASSERT_NOT,     /* 120 Negative lookahead */
  OP_ASSERTBACK,     /* 121 Positive lookbehind */
  OP_ASSERTBACK_NOT, /* 122 Negative lookbehind */

  /* ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately
  after the assertions, with ONCE first, as there's a test for >= ONCE for a
  subpattern that isn't an assertion. The POS versions must immediately follow
  the non-POS versions in each case. */

  OP_ONCE,           /* 123 Atomic group, contains captures */
  OP_ONCE_NC,        /* 124 Atomic group containing no captures */
  OP_BRA,            /* 125 Start of non-capturing bracket */
  OP_BRAPOS,         /* 126 Ditto, with unlimited, possessive repeat */
  OP_CBRA,           /* 127 Start of capturing bracket */
  OP_CBRAPOS,        /* 128 Ditto, with unlimited, possessive repeat */
  OP_COND,           /* 129 Conditional group */

  /* These five must follow the previous five, in the same order. There's a
  check for >= SBRA to distinguish the two sets. */

  OP_SBRA,           /* 130 Start of non-capturing bracket, check empty  */
  OP_SBRAPOS,        /* 131 Ditto, with unlimited, possessive repeat */
  OP_SCBRA,          /* 132 Start of capturing bracket, check empty */
  OP_SCBRAPOS,       /* 133 Ditto, with unlimited, possessive repeat */
  OP_SCOND,          /* 134 Conditional group, check empty */

  /* The next two pairs must (respectively) be kept together. */

  OP_CREF,           /* 135 Used to hold a capture number as condition */
  OP_NCREF,          /* 136 Same, but generated by a name reference*/
  OP_RREF,           /* 137 Used to hold a recursion number as condition */
  OP_NRREF,          /* 138 Same, but generated by a name reference*/
  OP_DEF,            /* 139 The DEFINE condition */

  OP_BRAZERO,        /* 140 These two must remain together and in this */
  OP_BRAMINZERO,     /* 141 order. */
  OP_BRAPOSZERO,     /* 142 */

  /* These are backtracking control verbs */

  OP_MARK,           /* 143 always has an argument */
  OP_PRUNE,          /* 144 */
  OP_PRUNE_ARG,      /* 145 same, but with argument */
  OP_SKIP,           /* 146 */
  OP_SKIP_ARG,       /* 147 same, but with argument */
  OP_THEN,           /* 148 */
  OP_THEN_ARG,       /* 149 same, but with argument */
  OP_COMMIT,         /* 150 */

  /* These are forced failure and success verbs */

  OP_FAIL,           /* 151 */
  OP_ACCEPT,         /* 152 */
  OP_ASSERT_ACCEPT,  /* 153 Used inside assertions */
  OP_CLOSE,          /* 154 Used before OP_ACCEPT to close open captures */

  /* This is used to skip a subpattern with a {0} quantifier */

  OP_SKIPZERO,       /* 155 */

  /* This is not an opcode, but is used to check that tables indexed by opcode
  are the correct length, in order to catch updating errors - there have been
  some in the past. */

  OP_TABLE_LENGTH
};

/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro
definitions that follow must also be updated to match. There are also tables
called "coptable" and "poptable" in DFAEXEC8.c that must be updated. */


/* This macro defines textual names for all the opcodes. These are used only
for debugging, and some of them are only partial names. The macro is referenced
only in PRINTIN8.c, which fills out the full names in many cases (and in
some cases doesn't actually use these names at all). */

#define OP_NAME_LIST \
  "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d",         \
  "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte",         \
  "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v",           \
  "extuni",  "\\Z", "\\z",                                        \
  "", "", "$", "$", "char", "chari", "not", "noti",             \
  "*", "*?", "+", "+?", "?", "??",                                \
  "{", "{", "{",                                                  \
  "*+","++", "?+", "{",                                           \
  "*", "*?", "+", "+?", "?", "??",                                \
  "{", "{", "{",                                                  \
  "*+","++", "?+", "{",                                           \
  "*", "*?", "+", "+?", "?", "??",                                \
  "{", "{", "{",                                                  \
  "*+","++", "?+", "{",                                           \
  "*", "*?", "+", "+?", "?", "??",                                \
  "{", "{", "{",                                                  \
  "*+","++", "?+", "{",                                           \
  "*", "*?", "+", "+?", "?", "??", "{", "{", "{",                 \
  "*+","++", "?+", "{",                                           \
  "*", "*?", "+", "+?", "?", "??", "{", "{",                      \
  "class", "nclass", "xclass", "Ref", "Refi",                     \
  "Recurse", "Callout",                                           \
  "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos",                  \
  "Reverse", "Assert", "Assert not", "AssertB", "AssertB not",    \
  "Once", "Once_NC",                                              \
  "Bra", "BraPos", "CBra", "CBraPos",                             \
  "Cond",                                                         \
  "SBra", "SBraPos", "SCBra", "SCBraPos",                         \
  "SCond",                                                        \
  "Cond ref", "Cond nref", "Cond rec", "Cond nrec", "Cond def",   \
  "Brazero", "Braminzero", "Braposzero",                          \
  "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP",                  \
  "*THEN", "*THEN", "*COMMIT", "*FAIL",                           \
  "*ACCEPT", "*ASSERT_ACCEPT",                                    \
  "Close", "Skip zero"


/* This macro defines the length of fixed length operations in the compiled
regex. The lengths are used when searching for specific things, and also in the
debugging printing of a compiled regex. We use a macro so that it can be
defined close to the definitions of the opcodes themselves.

As things have been extended, some of these are no longer fixed lenths, but are
minima instead. For example, the length of a single-character repeat may vary
in UTF-8 mode. The code that uses this table must know about such things. */

#define OP_LENGTHS \
  1,                             /* End                                    */ \
  1, 1, 1, 1, 1,                 /* \A, \G, \K, \B, \b                     */ \
  1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */ \
  1, 1, 1,                       /* Any, AllAny, Anybyte                   */ \
  3, 3,                          /* \P, \p                                 */ \
  1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */ \
  1,                             /* \X                                     */ \
  1, 1, 1, 1, 1, 1,              /* \Z, \z, , M, $, $M                   */ \
  2,                             /* Char  - the minimum length             */ \
  2,                             /* Chari  - the minimum length            */ \
  2,                             /* not                                    */ \
  2,                             /* noti                                   */ \
  /* Positive single-char repeats                             ** These are */ \
  2, 2, 2, 2, 2, 2,              /* *, *?, +, +?, ?, ??       ** minima in */ \
  2+IMM2_SIZE, 2+IMM2_SIZE,      /* upto, minupto             ** mode      */ \
  2+IMM2_SIZE,                   /* exact                                  */ \
  2, 2, 2, 2+IMM2_SIZE,          /* *+, ++, ?+, upto+                      */ \
  2, 2, 2, 2, 2, 2,              /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8     */ \
  2+IMM2_SIZE, 2+IMM2_SIZE,      /* upto I, minupto I                      */ \
  2+IMM2_SIZE,                   /* exact I                                */ \
  2, 2, 2, 2+IMM2_SIZE,          /* *+I, ++I, ?+I, upto+I                  */ \
  /* Negative single-char repeats - only for chars < 256                   */ \
  2, 2, 2, 2, 2, 2,              /* NOT *, *?, +, +?, ?, ??                */ \
  2+IMM2_SIZE, 2+IMM2_SIZE,      /* NOT upto, minupto                      */ \
  2+IMM2_SIZE,                   /* NOT exact                              */ \
  2, 2, 2, 2+IMM2_SIZE,          /* Possessive NOT *, +, ?, upto           */ \
  2, 2, 2, 2, 2, 2,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */ \
  2+IMM2_SIZE, 2+IMM2_SIZE,      /* NOT upto I, minupto I                  */ \
  2+IMM2_SIZE,                   /* NOT exact I                            */ \
  2, 2, 2, 2+IMM2_SIZE,          /* Possessive NOT *I, +I, ?I, upto I      */ \
  /* Positive type repeats                                                 */ \
  2, 2, 2, 2, 2, 2,              /* Type *, *?, +, +?, ?, ??               */ \
  2+IMM2_SIZE, 2+IMM2_SIZE,      /* Type upto, minupto                     */ \
  2+IMM2_SIZE,                   /* Type exact                             */ \
  2, 2, 2, 2+IMM2_SIZE,          /* Possessive *+, ++, ?+, upto+           */ \
  /* Character class & ref repeats                                         */ \
  1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */ \
  1+2*IMM2_SIZE, 1+2*IMM2_SIZE,  /* CRRANGE, CRMINRANGE                    */ \
  1+(32/sizeof(pcre_uchar)),     /* CLASS                                  */ \
  1+(32/sizeof(pcre_uchar)),     /* NCLASS                                 */ \
  0,                             /* XCLASS - variable length               */ \
  1+IMM2_SIZE,                   /* REF                                    */ \
  1+IMM2_SIZE,                   /* REFI                                   */ \
  1+LINK_SIZE,                   /* RECURSE                                */ \
  2+2*LINK_SIZE,                 /* CALLOUT                                */ \
  1+LINK_SIZE,                   /* Alt                                    */ \
  1+LINK_SIZE,                   /* Ket                                    */ \
  1+LINK_SIZE,                   /* KetRmax                                */ \
  1+LINK_SIZE,                   /* KetRmin                                */ \
  1+LINK_SIZE,                   /* KetRpos                                */ \
  1+LINK_SIZE,                   /* Reverse                                */ \
  1+LINK_SIZE,                   /* Assert                                 */ \
  1+LINK_SIZE,                   /* Assert not                             */ \
  1+LINK_SIZE,                   /* Assert behind                          */ \
  1+LINK_SIZE,                   /* Assert behind not                      */ \
  1+LINK_SIZE,                   /* ONCE                                   */ \
  1+LINK_SIZE,                   /* ONCE_NC                                */ \
  1+LINK_SIZE,                   /* BRA                                    */ \
  1+LINK_SIZE,                   /* BRAPOS                                 */ \
  1+LINK_SIZE+IMM2_SIZE,         /* CBRA                                   */ \
  1+LINK_SIZE+IMM2_SIZE,         /* CBRAPOS                                */ \
  1+LINK_SIZE,                   /* COND                                   */ \
  1+LINK_SIZE,                   /* SBRA                                   */ \
  1+LINK_SIZE,                   /* SBRAPOS                                */ \
  1+LINK_SIZE+IMM2_SIZE,         /* SCBRA                                  */ \
  1+LINK_SIZE+IMM2_SIZE,         /* SCBRAPOS                               */ \
  1+LINK_SIZE,                   /* SCOND                                  */ \
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* CREF, NCREF                            */ \
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* RREF, NRREF                            */ \
  1,                             /* DEF                                    */ \
  1, 1, 1,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */ \
  3, 1, 3,                       /* MARK, PRUNE, PRUNE_ARG                 */ \
  1, 3,                          /* SKIP, SKIP_ARG                         */ \
  1, 3,                          /* THEN, THEN_ARG                         */ \
  1, 1, 1, 1,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */ \
  1+IMM2_SIZE, 1                 /* CLOSE, SKIPZERO                        */

/* A magic value for OP_RREF and OP_NRREF to indicate the "any recursion"
condition. */

#define RREF_ANY  0xffff

/* Compile time error code numbers. They are given names so that they can more
easily be tracked. When a new number is added, the table called eint in
PCRPOSIX.c must be updated. */

enum { ERR0,  ERR1,  ERR2,  ERR3,  ERR4,  ERR5,  ERR6,  ERR7,  ERR8,  ERR9,
       ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19,
       ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29,
       ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39,
       ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49,
       ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
       ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69,
       ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERRCOUNT };

/* JIT compiling modes. The function list is indexed by them. */
enum { JIT_COMPILE, JIT_PARTIAL_SOFT_COMPILE, JIT_PARTIAL_HARD_COMPILE,
       JIT_NUMBER_OF_COMPILE_MODES };

/* The real format of the start of the pcre block; the index of names and the
code vector run on as long as necessary after the end. We store an explicit
offset to the name table so that if a regex is compiled on one host, saved, and
then run on another where the size of pointers is different, all might still
be well. For the case of compiled-on-4 and run-on-8, we include an extra
pointer that is always NULL. For future-proofing, a few dummy fields were
originally included - even though you can never get this planning right - but
there is only one left now.

NOTE NOTE NOTE:
Because people can now save and re-use compiled patterns, any additions to this
structure should be made at the end, and something earlier (e.g. a new
flag in the options or one of the dummy fields) should indicate that the new
fields are present. Currently PCRE always sets the dummy fields to zero.
NOTE NOTE NOTE
*/

#ifdef COMPILE_PCRE8
#define REAL_PCRE real_pcre
#else
#define REAL_PCRE real_pcre16
#endif

typedef struct REAL_PCRE {
  pcre_uint32 magic_number;
  pcre_uint32 size;               /* Total that was malloced */
  pcre_uint32 options;            /* Public options */
  pcre_uint16 flags;              /* Private flags */
  pcre_uint16 max_lookbehind;     /* Longest lookbehind (characters) */
  pcre_uint16 top_bracket;        /* Highest numbered group */
  pcre_uint16 top_backref;        /* Highest numbered back reference */
  pcre_uint16 first_char;         /* Starting character */
  pcre_uint16 req_char;           /* This character must be seen */
  pcre_uint16 name_table_offset;  /* Offset to name table that follows */
  pcre_uint16 name_entry_size;    /* Size of any name items */
  pcre_uint16 name_count;         /* Number of name items */
  pcre_uint16 ref_count;          /* Reference count */
  const pcre_uint8 *tables;       /* Pointer to tables or NULL for std */
  const pcre_uint8 *nullpad;      /* NULL padding */
} REAL_PCRE;

/* The format of the block used to store data from STUDY8(). The same
remark (see NOTE above) about extending this structure applies. */

typedef struct pcre_study_data {
  pcre_uint32 size;               /* Total that was malloced */
  pcre_uint32 flags;              /* Private flags */
  pcre_uint8 start_bits[32];      /* Starting char bits */
  pcre_uint32 minlength;          /* Minimum subject length */
} pcre_study_data;

/* Structure for building a chain of open capturing subpatterns during
compiling, so that instructions to close them can be compiled when (*ACCEPT) is
encountered. This is also used to identify subpatterns that contain recursive
back references to themselves, so that they can be made atomic. */

typedef struct open_capitem {
  struct open_capitem *next;    /* Chain link */
  pcre_uint16 number;           /* Capture number */
  pcre_uint16 flag;             /* Set TRUE if recursive back ref */
} open_capitem;

/* Structure for passing "static" information around between the functions
doing the compiling, so that they are thread-safe. */

typedef struct compile_data {
  const pcre_uint8 *lcc;            /* Points to lower casing table */
  const pcre_uint8 *fcc;            /* Points to case-flipping table */
  const pcre_uint8 *cbits;          /* Points to character type table */
  const pcre_uint8 *ctypes;         /* Points to table of type maps */
  const pcre_uchar *start_workspace;/* The start of working space */
  const pcre_uchar *start_code;     /* The start of the compiled code */
  const pcre_uchar *start_pattern;  /* The start of the pattern */
  const pcre_uchar *end_pattern;    /* The end of the pattern */
  open_capitem *open_caps;          /* Chain of open capture items */
  pcre_uchar *hwm;                  /* High watermark of workspace */
  pcre_uchar *name_table;           /* The name/number table */
  int  names_found;                 /* Number of entries so far */
  int  name_entry_size;             /* Size of each entry */
  int  workspace_size;              /* Size of workspace */
  int  bracount;                    /* Count of capturing parens as we compile */
  int  final_bracount;              /* Saved value after first pass */
  int  max_lookbehind;              /* Maximum lookbehind (characters) */
  int  top_backref;                 /* Maximum back reference */
  unsigned int backref_map;         /* Bitmap of low back refs */
  int  assert_depth;                /* Depth of nested assertions */
  int  external_options;            /* External (initial) options */
  int  external_flags;              /* External flag bits to be set */
  int  req_varyopt;                 /* "After variable item" flag for reqbyte */
  BOOL had_accept;                  /* (*ACCEPT) encountered */
  BOOL check_lookbehind;            /* Lookbehinds need later checking */
  int  nltype;                      /* Newline type */
  int  nllen;                       /* Newline string length */
  pcre_uchar nl[4];                 /* Newline string when fixed length */
} compile_data;

/* Structure for maintaining a chain of pointers to the currently incomplete
branches, for testing for left recursion while compiling. */

typedef struct branch_chain {
  struct branch_chain *outer;
  pcre_uchar *current_branch;
} branch_chain;

/* Structure for items in a linked list that represents an explicit recursive
call within the pattern; used by PCREXEC8(). */

typedef struct recursion_info {
  struct recursion_info *prevrec; /* Previous recursion record (or NULL) */
  int group_num;                  /* Number of group that was called */
  int *offset_save;               /* Pointer to start of saved offsets */
  int saved_max;                  /* Number of saved offsets */
  PCRE_PUCHAR subject_position;   /* Position at start of recursion */
} recursion_info;

/* A similar structure for DFAEXEC8(). */

typedef struct dfa_recursion_info {
  struct dfa_recursion_info *prevrec;
  int group_num;
  PCRE_PUCHAR subject_position;
} dfa_recursion_info;

/* Structure for building a chain of data for holding the values of the subject
pointer at the start of each subpattern, so as to detect when an empty string
has been matched by a subpattern - to break infinite loops; used by
PCREXEC8(). */

typedef struct eptrblock {
  struct eptrblock *epb_prev;
  PCRE_PUCHAR epb_saved_eptr;
} eptrblock;


/* Structure for passing "static" information around between the functions
doing traditional NFA matching, so that they are thread-safe. */

typedef struct match_data {
  unsigned long int match_call_count;      /* As it says */
  unsigned long int match_limit;           /* As it says */
  unsigned long int match_limit_recursion; /* As it says */
  int   *offset_vector;           /* Offset vector */
  int    offset_end;              /* One past the end */
  int    offset_max;              /* The maximum usable for return data */
  int    nltype;                  /* Newline type */
  int    nllen;                   /* Newline string length */
  int    name_count;              /* Number of names in name table */
  int    name_entry_size;         /* Size of entry in names table */
  pcre_uchar *name_table;         /* Table of names */
  pcre_uchar nl[4];               /* Newline string when fixed */
  const  pcre_uint8 *lcc;         /* Points to lower casing table */
  const  pcre_uint8 *fcc;         /* Points to case-flipping table */
  const  pcre_uint8 *ctypes;      /* Points to table of type maps */
  BOOL   offset_overflow;         /* Set if too many extractions */
  BOOL   notbol;                  /* NOTBOL flag */
  BOOL   noteol;                  /* NOTEOL flag */
  BOOL   utf;                     /* UTF-8 / UTF-16 flag */
  BOOL   jscript_compat;          /* JAVASCRIPT_COMPAT flag */
  BOOL   use_ucp;                 /* PCRE_UCP flag */
  BOOL   endonly;                 /* Dollar not before final \n */
  BOOL   notempty;                /* Empty string match not wanted */
  BOOL   notempty_atstart;        /* Empty string match at start not wanted */
  BOOL   hitend;                  /* Hit the end of the subject at some point */
  BOOL   bsr_anycrlf;             /* \R is just any CRLF, not full Unicode */
  BOOL   hasthen;                 /* Pattern contains (*THEN) */
  BOOL   ignore_skip_arg;         /* For re-run when SKIP name not found */
  const  pcre_uchar *start_code;  /* For use when recursing */
  PCRE_PUCHAR start_subject;      /* Start of the subject string */
  PCRE_PUCHAR end_subject;        /* End of the subject string */
  PCRE_PUCHAR start_match_ptr;    /* Start of matched string */
  PCRE_PUCHAR end_match_ptr;      /* Subject position at end match */
  PCRE_PUCHAR start_used_ptr;     /* Earliest consulted character */
  int    partial;                 /* PARTIAL options */
  int    end_offset_top;          /* Highwater mark at end of match */
  int    capture_last;            /* Most recent capture number */
  int    start_offset;            /* The start offset value */
  int    match_function_type;     /* Set for certain special calls of MATCH() */
  eptrblock *eptrchain;           /* Chain of eptrblocks for tail recursions */
  int    eptrn;                   /* Next free eptrblock */
  recursion_info *recursive;      /* Linked list of recursion data */
  void  *callout_data;            /* To pass back to callouts */
  const  pcre_uchar *mark;        /* Mark pointer to pass back on success */
  const  pcre_uchar *nomatch_mark;/* Mark pointer to pass back on failure */
  const  pcre_uchar *once_target; /* Where to back up to for atomic groups */
#ifdef NO_RECURSE
  void  *match_frames_base;       /* For remembering malloc'd frames */
#endif
} match_data;

/* A similar structure is used for the same purpose by the DFA matching
functions. */

typedef struct dfa_match_data {
  const pcre_uchar *start_code;     /* Start of the compiled pattern */
  const pcre_uchar *start_subject ; /* Start of the subject string */
  const pcre_uchar *end_subject;    /* End of subject string */
  const pcre_uchar *start_used_ptr; /* Earliest consulted character */
  const pcre_uint8 *tables;         /* Character tables */
  int   start_offset;               /* The start offset value */
  int   moptions;                   /* Match options */
  int   poptions;                   /* Pattern options */
  int   nltype;                     /* Newline type */
  int   nllen;                      /* Newline string length */
  pcre_uchar nl[4];                 /* Newline string when fixed */
  void *callout_data;               /* To pass back to callouts */
  dfa_recursion_info *recursive;    /* Linked list of recursion data */
} dfa_match_data;

/* Bit definitions for entries in the pcre_ctypes table. */

#define ctype_space   0x01
#define ctype_letter  0x02
#define ctype_digit   0x04
#define ctype_xdigit  0x08
#define ctype_word    0x10   /* alphanumeric or '_' */
#define ctype_meta    0x80   /* regexp meta char or zero (end pattern) */

/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
of bits for a class map. Some classes are built by combining these tables. */

#define cbit_space     0      /* [:space:] or \s */
#define cbit_xdigit   32      /* [:xdigit:] */
#define cbit_digit    64      /* [:digit:] or \d */
#define cbit_upper    96      /* [:upper:] */
#define cbit_lower   128      /* [:lower:] */
#define cbit_word    160      /* [:word:] or \w */
#define cbit_graph   192      /* [:graph:] */
#define cbit_print   224      /* [:print:] */
#define cbit_punct   256      /* [:punct:] */
#define cbit_cntrl   288      /* [:cntrl:] */
#define cbit_length  320      /* Length of the cbits table */

/* Offsets of the various tables from the base tables pointer, and
total length. */

#define lcc_offset      0
#define fcc_offset    256
#define cbits_offset  512
#define ctypes_offset (cbits_offset + cbit_length)
#define tables_length (ctypes_offset + 256)

/* Internal function and data prefixes. */

#ifdef COMPILE_PCRE8
#ifndef PUBL
#define PUBL(name) pcre_##name
#endif
#ifndef PRIV
#define PRIV(name) _pcre_##name
#endif
#else /* COMPILE_PCRE8 */
#ifdef COMPILE_PCRE16
#ifndef PUBL
#define PUBL(name) pcre16_##name
#endif
#ifndef PRIV
#define PRIV(name) _pcre16_##name
#endif
#else
#error Unsupported compiling mode
#endif /* COMPILE_PCRE16 */
#endif /* COMPILE_PCRE8 */

/* Layout of the UCP type table that translates property names into types and
codes. Each entry used to point directly to a name, but to reduce the number of
relocations in shared libraries, it now has an offset into a single string
instead. */

typedef struct {
  pcre_uint16 name_offset;
  pcre_uint16 type;
  pcre_uint16 value;
} ucp_type_table;


/* Internal shared data tables. These are tables that are used by more than one
of the exported public functions. They have to be "external" in the C sense,
but are not part of the PCRE public API. The data for these tables is in the
TABLES8.c module. */

#ifdef COMPILE_PCRE8

extern const int            PRIV(utf8_table1)[];
extern const int            PRIV(utf8_table1_size);
extern const int            PRIV(utf8_table2)[];
extern const int            PRIV(utf8_table3)[];
extern const pcre_uint8     PRIV(utf8_table4)[];

#endif /* COMPILE_PCRE8 */

extern const char           PRIV(utt_names)[];
extern const ucp_type_table PRIV(utt)[];
extern const int            PRIV(utt_size);

extern const pcre_uint8     PRIV(default_tables)[];

extern const pcre_uint8     PRIV(OP_lengths)[];


/* Internal shared functions. These are functions that are used by more than
one of the exported public functions. They have to be "external" in the C
sense, but are not part of the PCRE public API. */

/* String comparison functions. */
#ifdef COMPILE_PCRE8

#define STRCMP_UC_UC(str1, str2) \
  strcmp((char *)(str1), (char *)(str2))
#define STRCMP_UC_C8(str1, str2) \
  strcmp((char *)(str1), (str2))
#define STRNCMP_UC_UC(str1, str2, num) \
  strncmp((char *)(str1), (char *)(str2), (num))
#define STRNCMP_UC_C8(str1, str2, num) \
  strncmp((char *)(str1), (str2), (num))
#define STRLEN_UC(str) strlen((const char *)str)

#else

extern int               PRIV(strcmp_uc_uc)(const pcre_uchar *,
                           const pcre_uchar *);
extern int               PRIV(strcmp_uc_c8)(const pcre_uchar *,
                           const char *);
extern int               PRIV(strncmp_uc_uc)(const pcre_uchar *,
                           const pcre_uchar *, unsigned int num);
extern int               PRIV(strncmp_uc_c8)(const pcre_uchar *,
                           const char *, unsigned int num);
extern unsigned int      PRIV(strlen_uc)(const pcre_uchar *str);

#define STRCMP_UC_UC(str1, str2) \
  PRIV(strcmp_uc_uc)((str1), (str2))
#define STRCMP_UC_C8(str1, str2) \
  PRIV(strcmp_uc_c8)((str1), (str2))
#define STRNCMP_UC_UC(str1, str2, num) \
  PRIV(strncmp_uc_uc)((str1), (str2), (num))
#define STRNCMP_UC_C8(str1, str2, num) \
  PRIV(strncmp_uc_c8)((str1), (str2), (num))
#define STRLEN_UC(str) PRIV(strlen_uc)(str)

#endif /* COMPILE_PCRE8 */

extern const pcre_uchar *PRIV(find_bracket)(const pcre_uchar *, BOOL, int);
extern BOOL              PRIV(is_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR,
                           int *, BOOL);
extern int               PRIV(ord2utf)(pcre_uint32, pcre_uchar *);
extern int               PRIV(valid_utf)(PCRE_PUCHAR, int, int *);
extern BOOL              PRIV(was_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR,
                           int *, BOOL);
extern BOOL              PRIV(xclass)(int, const pcre_uchar *, BOOL);

#ifdef SUPPORT_JIT
extern void              PRIV(jit_compile)(const REAL_PCRE *,
                           PUBL(extra) *, int);
extern int               PRIV(jit_exec)(const REAL_PCRE *, const PUBL(extra) *,
                           const pcre_uchar *, int, int, int, int *, int);
extern void              PRIV(jit_free)(void *);
extern int               PRIV(jit_get_size)(void *);
extern const char*       PRIV(jit_get_target)(void);
#endif

/* Unicode character database (UCD) */

typedef struct {
  pcre_uint8 script;
  pcre_uint8 chartype;
  pcre_int32 other_case;
} ucd_record;

extern const ucd_record  PRIV(ucd_records)[];
extern const pcre_uint8  PRIV(ucd_stage1)[];
extern const pcre_uint16 PRIV(ucd_stage2)[];
extern const int         PRIV(ucp_gentype)[];
#ifdef SUPPORT_JIT
extern const int         PRIV(ucp_typerange)[];
#endif

#ifdef SUPPORT_UCP
/* UCD access macros */

#define UCD_BLOCK_SIZE 128
#define GET_UCD(ch) (PRIV(ucd_records) + \
        PRIV(ucd_stage2)[PRIV(ucd_stage1)[(ch) / UCD_BLOCK_SIZE] * \
        UCD_BLOCK_SIZE + (ch) % UCD_BLOCK_SIZE])

#define UCD_CHARTYPE(ch)  GET_UCD(ch)->chartype
#define UCD_SCRIPT(ch)    GET_UCD(ch)->script
#define UCD_CATEGORY(ch)  PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
#define UCD_OTHERCASE(ch) (ch + GET_UCD(ch)->other_case)

#endif /* SUPPORT_UCP */

#endif

/* End of pcre_internal.h */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_internal.h converted to INTERNA8*/
/*autoconv-0013 INTERNA8 line: 132 pcretest replaced by PCRETEST*/
/*autoconv-0013 INTERNA8 line: 209 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 INTERNA8 line: 318 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 INTERNA8 line: 321 pcre_exec replaced by PCREXEC8*/
/*autoconv-0011 INTERNA8 line: 335 pcre.h replaced by PCRE.h*/
/*autoconv-0011 INTERNA8 line: 336 ucp.h replaced by UCP.h*/
/*autoconv-0013 INTERNA8 line: 865 pcre_study replaced by STUDY8*/
/*autoconv-0013 INTERNA8 line: 1557 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 INTERNA8 line: 1799 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 INTERNA8 line: 1804 pcre_printint replaced by PRINTIN8*/
/*autoconv-0013 INTERNA8 line: 1939 pcreposix replaced by PCRPOSIX*/
/*autoconv-0013 INTERNA8 line: 1995 pcre_study replaced by STUDY8*/
/*autoconv-0013 INTERNA8 line: 2059 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 INTERNA8 line: 2069 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 INTERNA8 line: 2080 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 INTERNA8 line: 2232 pcre_tables replaced by TABLES8*/
./ ADD NAME=PCRECPP 
// Copyright (c) 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sanjay Ghemawat

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>      /* for SHRT_MIN, USHRT_MAX, etc */
#include <string.h>      /* for memcpy */
#include <assert.h>
#include <errno.h>
#include <string>
#include <algorithm>

#include "INTERNAP.h"
#include "PCRE.h"
#include "CPPH.h"
#include "pcre_stringpiece.h"


namespace PCRECPP {

// Maximum number of args we can set
static const int kMaxArgs = 16;
static const int kVecSize = (1 + kMaxArgs) * 3;  // results + PCRE workspace

// Special object that stands-in for no argument
Arg RE::no_arg((void*)NULL);

// This is for ABI compatibility with old versions of pcre (pre-7.6),
// which defined a global no_arg variable instead of putting it in the
// RE class.  This works on GCC >= 3, at least.  It definitely works
// for ELF, but may not for other object formats (Mach-O, for
// instance, does not support aliases.)  We could probably have a more
// inclusive test if we ever needed it.  (Note that not only the
// __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
// gnu-specific.)
#if defined(__GNUC__) && __GNUC__ >= 3 && defined(__ELF__)
# define ULP_AS_STRING(x)            ULP_AS_STRING_INTERNAL(x)
# define ULP_AS_STRING_INTERNAL(x)   #x
# define USER_LABEL_PREFIX_STR       ULP_AS_STRING(__USER_LABEL_PREFIX__)
extern Arg no_arg
  __attribute__((alias(USER_LABEL_PREFIX_STR "_ZN7pcrecpp2RE6no_argE")));
#endif

// If a regular expression has no error, its error_ field points here
static const string empty_string;

// If the user doesn't ask for any options, we just use this one
static RE_Options default_options;

void RE::Init(const string& pat, const RE_Options* options) {
  pattern_ = pat;
  if (options == NULL) {
    options_ = default_options;
  } else {
    options_ = *options;
  }
  error_ = &empty_string;
  re_full_ = NULL;
  re_partial_ = NULL;

  re_partial_ = Compile(UNANCHORED);
  if (re_partial_ != NULL) {
    re_full_ = Compile(ANCHOR_BOTH);
  }
}

void RE::Cleanup() {
  if (re_full_ != NULL)         (*pcre_free)(re_full_);
  if (re_partial_ != NULL)      (*pcre_free)(re_partial_);
  if (error_ != &empty_string)  delete error_;
}


RE::~RE() {
  Cleanup();
}


pcre* RE::Compile(Anchor anchor) {
  // First, convert RE_Options into pcre options
  int pcre_options = 0;
  pcre_options = options_.all_options();

  // Special treatment for anchoring.  This is needed because at
  // runtime pcre only provides an option for anchoring at the
  // beginning of a string (unless you use offset).
  //
  // There are three types of anchoring we want:
  //    UNANCHORED      Compile the original pattern, and use
  //                    a pcre unanchored match.
  //    ANCHOR_START    Compile the original pattern, and use
  //                    a pcre anchored match.
  //    ANCHOR_BOTH     Tack a "\z" to the end of the original pattern
  //                    and use a pcre anchored match.

  const char* compile_error;
  int eoffset;
  pcre* re;
  if (anchor != ANCHOR_BOTH) {
    re = COMPILE8(pattern_.c_str(), pcre_options,
                      &compile_error, &eoffset, NULL);
  } else {
    // Tack a '\z' at the end of RE.  Parenthesize it first so that
    // the '\z' applies to all top-level alternatives in the regexp.
    string wrapped = "(?:";  // A non-counting grouping operator
    wrapped += pattern_;
    wrapped += ")\\z";
    re = COMPILE8(wrapped.c_str(), pcre_options,
                      &compile_error, &eoffset, NULL);
  }
  if (re == NULL) {
    if (error_ == &empty_string) error_ = new string(compile_error);
  }
  return re;
}

/***** Matching interfaces *****/

bool RE::FullMatch(const StringPiece& text,
                   const Arg& ptr1,
                   const Arg& ptr2,
                   const Arg& ptr3,
                   const Arg& ptr4,
                   const Arg& ptr5,
                   const Arg& ptr6,
                   const Arg& ptr7,
                   const Arg& ptr8,
                   const Arg& ptr9,
                   const Arg& ptr10,
                   const Arg& ptr11,
                   const Arg& ptr12,
                   const Arg& ptr13,
                   const Arg& ptr14,
                   const Arg& ptr15,
                   const Arg& ptr16) const {
  const Arg* args[kMaxArgs];
  int n = 0;
  if (&ptr1  == &no_arg) goto done; args[n++] = &ptr1;
  if (&ptr2  == &no_arg) goto done; args[n++] = &ptr2;
  if (&ptr3  == &no_arg) goto done; args[n++] = &ptr3;
  if (&ptr4  == &no_arg) goto done; args[n++] = &ptr4;
  if (&ptr5  == &no_arg) goto done; args[n++] = &ptr5;
  if (&ptr6  == &no_arg) goto done; args[n++] = &ptr6;
  if (&ptr7  == &no_arg) goto done; args[n++] = &ptr7;
  if (&ptr8  == &no_arg) goto done; args[n++] = &ptr8;
  if (&ptr9  == &no_arg) goto done; args[n++] = &ptr9;
  if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
  if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
  if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
  if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
  if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
  if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
  if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
 done:

  int consumed;
  int vec[kVecSize];
  return DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize);
}

bool RE::PartialMatch(const StringPiece& text,
                      const Arg& ptr1,
                      const Arg& ptr2,
                      const Arg& ptr3,
                      const Arg& ptr4,
                      const Arg& ptr5,
                      const Arg& ptr6,
                      const Arg& ptr7,
                      const Arg& ptr8,
                      const Arg& ptr9,
                      const Arg& ptr10,
                      const Arg& ptr11,
                      const Arg& ptr12,
                      const Arg& ptr13,
                      const Arg& ptr14,
                      const Arg& ptr15,
                      const Arg& ptr16) const {
  const Arg* args[kMaxArgs];
  int n = 0;
  if (&ptr1  == &no_arg) goto done; args[n++] = &ptr1;
  if (&ptr2  == &no_arg) goto done; args[n++] = &ptr2;
  if (&ptr3  == &no_arg) goto done; args[n++] = &ptr3;
  if (&ptr4  == &no_arg) goto done; args[n++] = &ptr4;
  if (&ptr5  == &no_arg) goto done; args[n++] = &ptr5;
  if (&ptr6  == &no_arg) goto done; args[n++] = &ptr6;
  if (&ptr7  == &no_arg) goto done; args[n++] = &ptr7;
  if (&ptr8  == &no_arg) goto done; args[n++] = &ptr8;
  if (&ptr9  == &no_arg) goto done; args[n++] = &ptr9;
  if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
  if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
  if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
  if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
  if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
  if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
  if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
 done:

  int consumed;
  int vec[kVecSize];
  return DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize);
}

bool RE::Consume(StringPiece* input,
                 const Arg& ptr1,
                 const Arg& ptr2,
                 const Arg& ptr3,
                 const Arg& ptr4,
                 const Arg& ptr5,
                 const Arg& ptr6,
                 const Arg& ptr7,
                 const Arg& ptr8,
                 const Arg& ptr9,
                 const Arg& ptr10,
                 const Arg& ptr11,
                 const Arg& ptr12,
                 const Arg& ptr13,
                 const Arg& ptr14,
                 const Arg& ptr15,
                 const Arg& ptr16) const {
  const Arg* args[kMaxArgs];
  int n = 0;
  if (&ptr1  == &no_arg) goto done; args[n++] = &ptr1;
  if (&ptr2  == &no_arg) goto done; args[n++] = &ptr2;
  if (&ptr3  == &no_arg) goto done; args[n++] = &ptr3;
  if (&ptr4  == &no_arg) goto done; args[n++] = &ptr4;
  if (&ptr5  == &no_arg) goto done; args[n++] = &ptr5;
  if (&ptr6  == &no_arg) goto done; args[n++] = &ptr6;
  if (&ptr7  == &no_arg) goto done; args[n++] = &ptr7;
  if (&ptr8  == &no_arg) goto done; args[n++] = &ptr8;
  if (&ptr9  == &no_arg) goto done; args[n++] = &ptr9;
  if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
  if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
  if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
  if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
  if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
  if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
  if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
 done:

  int consumed;
  int vec[kVecSize];
  if (DoMatchImpl(*input, ANCHOR_START, &consumed,
                  args, n, vec, kVecSize)) {
    input->remove_prefix(consumed);
    return true;
  } else {
    return false;
  }
}

bool RE::FindAndConsume(StringPiece* input,
                        const Arg& ptr1,
                        const Arg& ptr2,
                        const Arg& ptr3,
                        const Arg& ptr4,
                        const Arg& ptr5,
                        const Arg& ptr6,
                        const Arg& ptr7,
                        const Arg& ptr8,
                        const Arg& ptr9,
                        const Arg& ptr10,
                        const Arg& ptr11,
                        const Arg& ptr12,
                        const Arg& ptr13,
                        const Arg& ptr14,
                        const Arg& ptr15,
                        const Arg& ptr16) const {
  const Arg* args[kMaxArgs];
  int n = 0;
  if (&ptr1  == &no_arg) goto done; args[n++] = &ptr1;
  if (&ptr2  == &no_arg) goto done; args[n++] = &ptr2;
  if (&ptr3  == &no_arg) goto done; args[n++] = &ptr3;
  if (&ptr4  == &no_arg) goto done; args[n++] = &ptr4;
  if (&ptr5  == &no_arg) goto done; args[n++] = &ptr5;
  if (&ptr6  == &no_arg) goto done; args[n++] = &ptr6;
  if (&ptr7  == &no_arg) goto done; args[n++] = &ptr7;
  if (&ptr8  == &no_arg) goto done; args[n++] = &ptr8;
  if (&ptr9  == &no_arg) goto done; args[n++] = &ptr9;
  if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10;
  if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11;
  if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12;
  if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13;
  if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14;
  if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15;
  if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16;
 done:

  int consumed;
  int vec[kVecSize];
  if (DoMatchImpl(*input, UNANCHORED, &consumed,
                  args, n, vec, kVecSize)) {
    input->remove_prefix(consumed);
    return true;
  } else {
    return false;
  }
}

bool RE::Replace(const StringPiece& rewrite,
                 string *str) const {
  int vec[kVecSize];
  int matches = TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize);
  if (matches == 0)
    return false;

  string s;
  if (!Rewrite(&s, rewrite, *str, vec, matches))
    return false;

  assert(vec[0] >= 0);
  assert(vec[1] >= 0);
  str->replace(vec[0], vec[1] - vec[0], s);
  return true;
}

// Returns PCRE_NEWLINE_CRLF, PCRE_NEWLINE_CR, or PCRE_NEWLINE_LF.
// Note that PCRE_NEWLINE_CRLF is defined to be P_N_CR | P_N_LF.
// Modified by PH to add PCRE_NEWLINE_ANY and PCRE_NEWLINE_ANYCRLF.

static int NewlineMode(int pcre_options) {
  // TODO: if we can make it threadsafe, cache this var
  int newline_mode = 0;
  /* if (newline_mode) return newline_mode; */  // do this once it's cached
  if (pcre_options & (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|
                      PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF)) {
    newline_mode = (pcre_options &
                    (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|
                     PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF));
  } else {
    int newline;
    CONFIG8(PCRE_CONFIG_NEWLINE, &newline);
    if (newline == 10)
      newline_mode = PCRE_NEWLINE_LF;
    else if (newline == 13)
      newline_mode = PCRE_NEWLINE_CR;
    else if (newline == 3338)
      newline_mode = PCRE_NEWLINE_CRLF;
    else if (newline == -1)
      newline_mode = PCRE_NEWLINE_ANY;
    else if (newline == -2)
      newline_mode = PCRE_NEWLINE_ANYCRLF;
    else
      assert(NULL == "Unexpected return value from CONFIG8(NEWLINE)");
  }
  return newline_mode;
}

int RE::GlobalReplace(const StringPiece& rewrite,
                      string *str) const {
  int count = 0;
  int vec[kVecSize];
  string out;
  int start = 0;
  bool last_match_was_empty_string = false;

  while (start <= static_cast<int>(str->length())) {
    // If the previous match was for the empty string, we shouldn't
    // just match again: we'll match in the same way and get an
    // infinite loop.  Instead, we do the match in a special way:
    // anchored -- to force another try at the same position --
    // and with a flag saying that this time, ignore empty matches.
    // If this special match returns, that means there's a non-empty
    // match at this position as well, and we can continue.  If not,
    // we do what perl does, and just advance by one.
    // Notice that perl prints '@@@' for this;
    //    perl -le '$_ = "aa"; s/b*|aa/@/g; print'
    int matches;
    if (last_match_was_empty_string) {
      matches = TryMatch(*str, start, ANCHOR_START, false, vec, kVecSize);
      if (matches <= 0) {
        int matchend = start + 1;     // advance one character.
        // If the current char is CR and we're in CRLF mode, skip LF too.
        // Note it's better to call FULLINF8() than to examine
        // all_options(), since options_ could have changed bewteen
        // compile-time and now, but this is simpler and safe enough.
        // Modified by PH to add ANY and ANYCRLF.
        if (matchend < static_cast<int>(str->length()) &&
            (*str)[start] == '\r' && (*str)[matchend] == '\n' &&
            (NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF ||
             NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANY ||
             NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANYCRLF)) {
          matchend++;
        }
        // We also need to advance more than one char if we're in utf8 mode.
#ifdef SUPPORT_UTF8
        if (options_.utf8()) {
          while (matchend < static_cast<int>(str->length()) &&
                 ((*str)[matchend] & 0xc0) == 0x80)
            matchend++;
        }
#endif
        if (start < static_cast<int>(str->length()))
          out.append(*str, start, matchend - start);
        start = matchend;
        last_match_was_empty_string = false;
        continue;
      }
    } else {
      matches = TryMatch(*str, start, UNANCHORED, true, vec, kVecSize);
      if (matches <= 0)
        break;
    }
    int matchstart = vec[0], matchend = vec[1];
    assert(matchstart >= start);
    assert(matchend >= matchstart);
    out.append(*str, start, matchstart - start);
    Rewrite(&out, rewrite, *str, vec, matches);
    start = matchend;
    count++;
    last_match_was_empty_string = (matchstart == matchend);
  }

  if (count == 0)
    return 0;

  if (start < static_cast<int>(str->length()))
    out.append(*str, start, str->length() - start);
  swap(out, *str);
  return count;
}

bool RE::Extract(const StringPiece& rewrite,
                 const StringPiece& text,
                 string *out) const {
  int vec[kVecSize];
  int matches = TryMatch(text, 0, UNANCHORED, true, vec, kVecSize);
  if (matches == 0)
    return false;
  out->erase();
  return Rewrite(out, rewrite, text, vec, matches);
}

/*static*/ string RE::QuoteMeta(const StringPiece& unquoted) {
  string result;

  // Escape any ascii character not in [A-Za-z_0-9].
  //
  // Note that it's legal to escape a character even if it has no
  // special meaning in a regular expression -- so this function does
  // that.  (This also makes it identical to the perl function of the
  // same name; see `perldoc -f quotemeta`.)  The one exception is
  // escaping NUL: rather than doing backslash + NUL, like perl does,
  // we do '\0', because pcre itself doesn't take embedded NUL chars.
  for (int ii = 0; ii < unquoted.size(); ++ii) {
    // Note that using 'isalnum' here raises the benchmark time from
    // 32ns to 58ns:
    if (unquoted[ii] == '\0') {
      result += "\\0";
    } else if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') &&
               (unquoted[ii] < 'A' || unquoted[ii] > 'Z') &&
               (unquoted[ii] < '0' || unquoted[ii] > '9') &&
               unquoted[ii] != '_' &&
               // If this is the part of a UTF8 or Latin1 character, we need
               // to copy this byte without escaping.  Experimentally this is
               // what works correctly with the regexp library.
               !(unquoted[ii] & 128)) {
      result += '\\';
      result += unquoted[ii];
    } else {
      result += unquoted[ii];
    }
  }

  return result;
}

/***** Actual matching and rewriting code *****/

int RE::TryMatch(const StringPiece& text,
                 int startpos,
                 Anchor anchor,
                 bool empty_ok,
                 int *vec,
                 int vecsize) const {
  pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_;
  if (re == NULL) {
    //fprintf(stderr, "Matching against invalid re: %s\n", error_->c_str());
    return 0;
  }

  pcre_extra extra = { 0, 0, 0, 0, 0, 0 };
  if (options_.match_limit() > 0) {
    extra.flags |= PCRE_EXTRA_MATCH_LIMIT;
    extra.match_limit = options_.match_limit();
  }
  if (options_.match_limit_recursion() > 0) {
    extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
    extra.match_limit_recursion = options_.match_limit_recursion();
  }

  int options = 0;
  if (anchor != UNANCHORED)
    options |= PCRE_ANCHORED;
  if (!empty_ok)
    options |= PCRE_NOTEMPTY;

  int rc = PCREXEC8(re,              // The regular expression object
                     &extra,
                     (text.data() == NULL) ? "" : text.data(),
                     text.size(),
                     startpos,
                     options,
                     vec,
                     vecsize);

  // Handle errors
  if (rc == PCRE_ERROR_NOMATCH) {
    return 0;
  } else if (rc < 0) {
    //fprintf(stderr, "Unexpected return code: %d when matching '%s'\n",
    //        re, pattern_.c_str());
    return 0;
  } else if (rc == 0) {
    // PCREXEC8() returns 0 as a special case when the number of
    // capturing subpatterns exceeds the size of the vector.
    // When this happens, there is a match and the output vector
    // is filled, but we miss out on the positions of the extra subpatterns.
    rc = vecsize / 2;
  }

  return rc;
}

bool RE::DoMatchImpl(const StringPiece& text,
                     Anchor anchor,
                     int* consumed,
                     const Arg* const* args,
                     int n,
                     int* vec,
                     int vecsize) const {
  assert((1 + n) * 3 <= vecsize);  // results + PCRE workspace
  int matches = TryMatch(text, 0, anchor, true, vec, vecsize);
  assert(matches >= 0);  // TryMatch never returns negatives
  if (matches == 0)
    return false;

  *consumed = vec[1];

  if (n == 0 || args == NULL) {
    // We are not interested in results
    return true;
  }

  if (NumberOfCapturingGroups() < n) {
    // RE has fewer capturing groups than number of arg pointers passed in
    return false;
  }

  // If we got here, we must have matched the whole pattern.
  // We do not need (can not do) any more checks on the value of 'matches' here
  // -- see the comment for TryMatch.
  for (int i = 0; i < n; i++) {
    const int start = vec[2*(i+1)];
    const int limit = vec[2*(i+1)+1];
    if (!args[i]->Parse(text.data() + start, limit-start)) {
      // TODO: Should we indicate what the error was?
      return false;
    }
  }

  return true;
}

bool RE::DoMatch(const StringPiece& text,
                 Anchor anchor,
                 int* consumed,
                 const Arg* const args[],
                 int n) const {
  assert(n >= 0);
  size_t const vecsize = (1 + n) * 3;  // results + PCRE workspace
                                       // (as for kVecSize)
  int space[21];   // use stack allocation for small vecsize (common case)
  int* vec = vecsize <= 21 ? space : new int[vecsize];
  bool retval = DoMatchImpl(text, anchor, consumed, args, n, vec, (int)vecsize);
  if (vec != space) delete [] vec;
  return retval;
}

bool RE::Rewrite(string *out, const StringPiece &rewrite,
                 const StringPiece &text, int *vec, int veclen) const {
  for (const char *s = rewrite.data(), *end = s + rewrite.size();
       s < end; s++) {
    int c = *s;
    if (c == '\\') {
      c = *++s;
      if (isdigit(c)) {
        int n = (c - '0');
        if (n >= veclen) {
          //fprintf(stderr, requested group %d in regexp %.*s\n",
          //        n, rewrite.size(), rewrite.data());
          return false;
        }
        int start = vec[2 * n];
        if (start >= 0)
          out->append(text.data() + start, vec[2 * n + 1] - start);
      } else if (c == '\\') {
        *out += '\\';
      } else {
        //fprintf(stderr, "invalid rewrite pattern: %.*s\n",
        //        rewrite.size(), rewrite.data());
        return false;
      }
    } else {
      *out += c;
    }
  }
  return true;
}

// Return the number of capturing subpatterns, or -1 if the
// regexp wasn't valid on construction.
int RE::NumberOfCapturingGroups() const {
  if (re_partial_ == NULL) return -1;

  int result;
  int pcre_retval = FULLINF8(re_partial_,  // The regular expression object
                                  NULL,         // We did not study the pattern
                                  PCRE_INFO_CAPTURECOUNT,
                                  &result);
  assert(pcre_retval == 0);
  return result;
}

/***** Parsers for various types *****/

bool Arg::parse_null(const char* str, int n, void* dest) {
  // We fail if somebody asked us to store into a non-NULL void* pointer
  return (dest == NULL);
}

bool Arg::parse_string(const char* str, int n, void* dest) {
  if (dest == NULL) return true;
  reinterpret_cast<string*>(dest)->assign(str, n);
  return true;
}

bool Arg::parse_stringpiece(const char* str, int n, void* dest) {
  if (dest == NULL) return true;
  reinterpret_cast<StringPiece*>(dest)->set(str, n);
  return true;
}

bool Arg::parse_char(const char* str, int n, void* dest) {
  if (n != 1) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<char*>(dest)) = str[0];
  return true;
}

bool Arg::parse_uchar(const char* str, int n, void* dest) {
  if (n != 1) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<unsigned char*>(dest)) = str[0];
  return true;
}

// Largest number spec that we are willing to parse
static const int kMaxNumberLength = 32;

// REQUIRES "buf" must have length at least kMaxNumberLength+1
// REQUIRES "n > 0"
// Copies "str" into "buf" and null-terminates if necessary.
// Returns one of:
//      a. "str" if no termination is needed
//      b. "buf" if the string was copied and null-terminated
//      c. "" if the input was invalid and has no hope of being parsed
static const char* TerminateNumber(char* buf, const char* str, int n) {
  if ((n > 0) && isspace(*str)) {
    // We are less forgiving than the strtoxxx() routines and do not
    // allow leading spaces.
    return "";
  }

  // See if the character right after the input text may potentially
  // look like a digit.
  if (isdigit(str[n]) ||
      ((str[n] >= 'a') && (str[n] <= 'f')) ||
      ((str[n] >= 'A') && (str[n] <= 'F'))) {
    if (n > kMaxNumberLength) return ""; // Input too big to be a valid number
    memcpy(buf, str, n);
    buf[n] = '\0';
    return buf;
  } else {
    // We can parse right out of the supplied string, so return it.
    return str;
  }
}

bool Arg::parse_long_radix(const char* str,
                           int n,
                           void* dest,
                           int radix) {
  if (n == 0) return false;
  char buf[kMaxNumberLength+1];
  str = TerminateNumber(buf, str, n);
  char* end;
  errno = 0;
  long r = strtol(str, &end, radix);
  if (end != str + n) return false;   // Leftover junk
  if (errno) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<long*>(dest)) = r;
  return true;
}

bool Arg::parse_ulong_radix(const char* str,
                            int n,
                            void* dest,
                            int radix) {
  if (n == 0) return false;
  char buf[kMaxNumberLength+1];
  str = TerminateNumber(buf, str, n);
  if (str[0] == '-') return false;    // strtoul() on a negative number?!
  char* end;
  errno = 0;
  unsigned long r = strtoul(str, &end, radix);
  if (end != str + n) return false;   // Leftover junk
  if (errno) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<unsigned long*>(dest)) = r;
  return true;
}

bool Arg::parse_short_radix(const char* str,
                            int n,
                            void* dest,
                            int radix) {
  long r;
  if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
  if (r < SHRT_MIN || r > SHRT_MAX) return false;       // Out of range
  if (dest == NULL) return true;
  *(reinterpret_cast<short*>(dest)) = static_cast<short>(r);
  return true;
}

bool Arg::parse_ushort_radix(const char* str,
                             int n,
                             void* dest,
                             int radix) {
  unsigned long r;
  if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
  if (r > USHRT_MAX) return false;                      // Out of range
  if (dest == NULL) return true;
  *(reinterpret_cast<unsigned short*>(dest)) = static_cast<unsigned short>(r);
  return true;
}

bool Arg::parse_int_radix(const char* str,
                          int n,
                          void* dest,
                          int radix) {
  long r;
  if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
  if (r < INT_MIN || r > INT_MAX) return false;         // Out of range
  if (dest == NULL) return true;
  *(reinterpret_cast<int*>(dest)) = r;
  return true;
}

bool Arg::parse_uint_radix(const char* str,
                           int n,
                           void* dest,
                           int radix) {
  unsigned long r;
  if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
  if (r > UINT_MAX) return false;                       // Out of range
  if (dest == NULL) return true;
  *(reinterpret_cast<unsigned int*>(dest)) = r;
  return true;
}

bool Arg::parse_longlong_radix(const char* str,
                               int n,
                               void* dest,
                               int radix) {
#ifndef HAVE_LONG_LONG
  return false;
#else
  if (n == 0) return false;
  char buf[kMaxNumberLength+1];
  str = TerminateNumber(buf, str, n);
  char* end;
  errno = 0;
#if defined HAVE_STRTOQ
  long long r = strtoq(str, &end, radix);
#elif defined HAVE_STRTOLL
  long long r = strtoll(str, &end, radix);
#elif defined HAVE__STRTOI64
  long long r = _strtoi64(str, &end, radix);
#elif defined HAVE_STRTOIMAX
  long long r = strtoimax(str, &end, radix);
#else
#error parse_longlong_radix: cannot convert input to a long-long
#endif
  if (end != str + n) return false;   // Leftover junk
  if (errno) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<long long*>(dest)) = r;
  return true;
#endif   /* HAVE_LONG_LONG */
}

bool Arg::parse_ulonglong_radix(const char* str,
                                int n,
                                void* dest,
                                int radix) {
#ifndef HAVE_UNSIGNED_LONG_LONG
  return false;
#else
  if (n == 0) return false;
  char buf[kMaxNumberLength+1];
  str = TerminateNumber(buf, str, n);
  if (str[0] == '-') return false;    // strtoull() on a negative number?!
  char* end;
  errno = 0;
#if defined HAVE_STRTOQ
  unsigned long long r = strtouq(str, &end, radix);
#elif defined HAVE_STRTOLL
  unsigned long long r = strtoull(str, &end, radix);
#elif defined HAVE__STRTOI64
  unsigned long long r = _strtoui64(str, &end, radix);
#elif defined HAVE_STRTOIMAX
  unsigned long long r = strtoumax(str, &end, radix);
#else
#error parse_ulonglong_radix: cannot convert input to a long-long
#endif
  if (end != str + n) return false;   // Leftover junk
  if (errno) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<unsigned long long*>(dest)) = r;
  return true;
#endif   /* HAVE_UNSIGNED_LONG_LONG */
}

bool Arg::parse_double(const char* str, int n, void* dest) {
  if (n == 0) return false;
  static const int kMaxLength = 200;
  char buf[kMaxLength];
  if (n >= kMaxLength) return false;
  memcpy(buf, str, n);
  buf[n] = '\0';
  errno = 0;
  char* end;
  double r = strtod(buf, &end);
  if (end != buf + n) return false;   // Leftover junk
  if (errno) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<double*>(dest)) = r;
  return true;
}

bool Arg::parse_float(const char* str, int n, void* dest) {
  double r;
  if (!parse_double(str, n, &r)) return false;
  if (dest == NULL) return true;
  *(reinterpret_cast<float*>(dest)) = static_cast<float>(r);
  return true;
}


#define DEFINE_INTEGER_PARSERS(name)                                    \
  bool Arg::parse_##name(const char* str, int n, void* dest) {          \
    return parse_##name##_radix(str, n, dest, 10);                      \
  }                                                                     \
  bool Arg::parse_##name##_hex(const char* str, int n, void* dest) {    \
    return parse_##name##_radix(str, n, dest, 16);                      \
  }                                                                     \
  bool Arg::parse_##name##_octal(const char* str, int n, void* dest) {  \
    return parse_##name##_radix(str, n, dest, 8);                       \
  }                                                                     \
  bool Arg::parse_##name##_cradix(const char* str, int n, void* dest) { \
    return parse_##name##_radix(str, n, dest, 0);                       \
  }

DEFINE_INTEGER_PARSERS(short)      /*                                   */
DEFINE_INTEGER_PARSERS(ushort)     /*                                   */
DEFINE_INTEGER_PARSERS(int)        /* Don't use semicolons after these  */
DEFINE_INTEGER_PARSERS(uint)       /* statements because they can cause */
DEFINE_INTEGER_PARSERS(long)       /* compiler warnings if the checking */
DEFINE_INTEGER_PARSERS(ulong)      /* level is turned up high enough.   */
DEFINE_INTEGER_PARSERS(longlong)   /*                                   */
DEFINE_INTEGER_PARSERS(ulonglong)  /*                                   */

#undef DEFINE_INTEGER_PARSERS

}   // namespace PCRECPP
/*autoconv-0001 C:\projects\pcre-8.31\pcrecpp.cc converted to PCRECPP*/
/*autoconv-0010 PCRECPP line: 33 added HAVE_CONFIG_H*/
/*autoconv-0011 PCRECPP line: 36 config.h replaced by CONFIG.h*/
/*autoconv-0011 PCRECPP line: 49 pcrecpp_internal.h replaced by INTERNAP.h*/
/*autoconv-0011 PCRECPP line: 50 pcre.h replaced by PCRE.h*/
/*autoconv-0011 PCRECPP line: 51 pcrecpp.h replaced by CPPH.h*/
/*autoconv-0013 PCRECPP line: 55 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 PCRECPP line: 136 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRECPP line: 144 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRECPP line: 367 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRECPP line: 379 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRECPP line: 409 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRECPP line: 533 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRECPP line: 550 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRECPP line: 652 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRECPP line: 922 pcrecpp replaced by PCRECPP*/
./ ADD NAME=INTERNAP 
/*************************************************
*       Perl-Compatible Regular Expressions      *
*************************************************/

/*
Copyright (c) 2005, Google Inc.
All rights reserved.

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


#ifndef PCRECPP_INTERNAL_H
#define PCRECPP_INTERNAL_H

/* When compiling a DLL for Windows, the exported symbols have to be declared
using some MS magic. I found some useful information on this web page:
http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the
information there, using __declspec(dllexport) without "extern" we have a
definition; with "extern" we have a declaration. The settings here override the
setting in pcre.h. We use:

  PCRECPP_EXP_DECL       for declarations
  PCRECPP_EXP_DEFN       for definitions of exported functions

*/

#ifndef PCRECPP_EXP_DECL
#  ifdef _WIN32
#    ifndef PCRE_STATIC
#      define PCRECPP_EXP_DECL       extern __declspec(dllexport)
#      define PCRECPP_EXP_DEFN       __declspec(dllexport)
#    else
#      define PCRECPP_EXP_DECL       extern
#      define PCRECPP_EXP_DEFN
#    endif
#  else
#    define PCRECPP_EXP_DECL         extern
#    define PCRECPP_EXP_DEFN
#  endif
#endif

#endif  /* PCRECPP_INTERNAL_H */

/* End of pcrecpp_internal.h */
/*autoconv-0001 C:\projects\pcre-8.31\pcrecpp_internal.h converted to INTERNAP*/
./ ADD NAME=UCP 
/*************************************************
*          Unicode Property Table handler        *
*************************************************/

#ifndef _UCP_H
#define _UCP_H

/* This file contains definitions of the property values that are returned by
the UCD access macros. New values that are added for new releases of Unicode
should always be at the end of each enum, for backwards compatibility. */

/* These are the general character categories. */

enum {
  ucp_C,     /* Other */
  ucp_L,     /* Letter */
  ucp_M,     /* Mark */
  ucp_N,     /* Number */
  ucp_P,     /* Punctuation */
  ucp_S,     /* Symbol */
  ucp_Z      /* Separator */
};

/* These are the particular character types. */

enum {
  ucp_Cc,    /* Control */
  ucp_Cf,    /* Format */
  ucp_Cn,    /* Unassigned */
  ucp_Co,    /* Private use */
  ucp_Cs,    /* Surrogate */
  ucp_Ll,    /* Lower case letter */
  ucp_Lm,    /* Modifier letter */
  ucp_Lo,    /* Other letter */
  ucp_Lt,    /* Title case letter */
  ucp_Lu,    /* Upper case letter */
  ucp_Mc,    /* Spacing mark */
  ucp_Me,    /* Enclosing mark */
  ucp_Mn,    /* Non-spacing mark */
  ucp_Nd,    /* Decimal number */
  ucp_Nl,    /* Letter number */
  ucp_No,    /* Other number */
  ucp_Pc,    /* Connector punctuation */
  ucp_Pd,    /* Dash punctuation */
  ucp_Pe,    /* Close punctuation */
  ucp_Pf,    /* Final punctuation */
  ucp_Pi,    /* Initial punctuation */
  ucp_Po,    /* Other punctuation */
  ucp_Ps,    /* Open punctuation */
  ucp_Sc,    /* Currency symbol */
  ucp_Sk,    /* Modifier symbol */
  ucp_Sm,    /* Mathematical symbol */
  ucp_So,    /* Other symbol */
  ucp_Zl,    /* Line separator */
  ucp_Zp,    /* Paragraph separator */
  ucp_Zs     /* Space separator */
};

/* These are the script identifications. */

enum {
  ucp_Arabic,
  ucp_Armenian,
  ucp_Bengali,
  ucp_Bopomofo,
  ucp_Braille,
  ucp_Buginese,
  ucp_Buhid,
  ucp_Canadian_Aboriginal,
  ucp_Cherokee,
  ucp_Common,
  ucp_Coptic,
  ucp_Cypriot,
  ucp_Cyrillic,
  ucp_Deseret,
  ucp_Devanagari,
  ucp_Ethiopic,
  ucp_Georgian,
  ucp_Glagolitic,
  ucp_Gothic,
  ucp_Greek,
  ucp_Gujarati,
  ucp_Gurmukhi,
  ucp_Han,
  ucp_Hangul,
  ucp_Hanunoo,
  ucp_Hebrew,
  ucp_Hiragana,
  ucp_Inherited,
  ucp_Kannada,
  ucp_Katakana,
  ucp_Kharoshthi,
  ucp_Khmer,
  ucp_Lao,
  ucp_Latin,
  ucp_Limbu,
  ucp_Linear_B,
  ucp_Malayalam,
  ucp_Mongolian,
  ucp_Myanmar,
  ucp_New_Tai_Lue,
  ucp_Ogham,
  ucp_Old_Italic,
  ucp_Old_Persian,
  ucp_Oriya,
  ucp_Osmanya,
  ucp_Runic,
  ucp_Shavian,
  ucp_Sinhala,
  ucp_Syloti_Nagri,
  ucp_Syriac,
  ucp_Tagalog,
  ucp_Tagbanwa,
  ucp_Tai_Le,
  ucp_Tamil,
  ucp_Telugu,
  ucp_Thaana,
  ucp_Thai,
  ucp_Tibetan,
  ucp_Tifinagh,
  ucp_Ugaritic,
  ucp_Yi,
  /* New for Unicode 5.0: */
  ucp_Balinese,
  ucp_Cuneiform,
  ucp_Nko,
  ucp_Phags_Pa,
  ucp_Phoenician,
  /* New for Unicode 5.1: */
  ucp_Carian,
  ucp_Cham,
  ucp_Kayah_Li,
  ucp_Lepcha,
  ucp_Lycian,
  ucp_Lydian,
  ucp_Ol_Chiki,
  ucp_Rejang,
  ucp_Saurashtra,
  ucp_Sundanese,
  ucp_Vai,
  /* New for Unicode 5.2: */
  ucp_Avestan,
  ucp_Bamum,
  ucp_Egyptian_Hieroglyphs,
  ucp_Imperial_Aramaic,
  ucp_Inscriptional_Pahlavi,
  ucp_Inscriptional_Parthian,
  ucp_Javanese,
  ucp_Kaithi,
  ucp_Lisu,
  ucp_Meetei_Mayek,
  ucp_Old_South_Arabian,
  ucp_Old_Turkic,
  ucp_Samaritan,
  ucp_Tai_Tham,
  ucp_Tai_Viet,
  /* New for Unicode 6.0.0: */
  ucp_Batak,
  ucp_Brahmi,
  ucp_Mandaic,
  /* New for Unicode 6.1.0: */
  ucp_Chakma,
  ucp_Meroitic_Cursive,
  ucp_Meroitic_Hieroglyphs,
  ucp_Miao,
  ucp_Sharada,
  ucp_Sora_Sompeng,
  ucp_Takri
};

#endif

/* End of ucp.h */
/*autoconv-0001 C:\projects\pcre-8.31\ucp.h converted to UCP*/
./ ADD NAME=CONFIG 
/* config.h.  Generated from config.h.in by configure.  */
/* config.h.in.  Generated from configure.ac by autoheader.  */

/* This config.h was generated manually from config.h.grnrric for native z/OS.
Version 0.1
Changes by Ze'ev Atlas 2012.
The purpose of this particular version is for porting into native z/OS without
USS (Unix Services) and with EBCDIC in whatever flavor as the character set.
This version supports EBCDIC only.  That implies by default (dictated by the
pcre package) neither UTF-8, nor UTF-16 support.  Thus, also No support for any
IBM DBCS has been attempted!
Also
* this version does not support C++!
* this version does not support JIT!
See documentation for details */
/* ZA - general z/OS signal*/
#define NATIVE_ZOS 1
/* ZA - EBCDIC codepage used */
/* Change the your target EBCDIC codepage to 1 and leave the rest as 0.
   These definitions might not be needed and if so would be deprecated 
   and removed in subsequent releases.  Current version supports only 
   IBM1047 and the definition is not used anywhere in the code */
/* most common in US */
#define IBM1047 1
/* Hebrew */
#define IBM424 0 
/* Greek */
#define IBM875 0
/* Turkish */
#define IBM1026 0
/* Older US version 037 */
#define IBM1140 0
/* CP500 */
#define IBM1148 0
/* UK - maybe superseded by CP500 - investigate */
#define IBM285 0
#if IBM1047 + IBM424 + IBM875 + IBM1026 + IBM1140 + IBM1148 + IBM285 != 1
#error please define one and only one EBCDIC codepage
#endif

/* On Unix-like systems config.h.in is converted by "configure" into config.h.
Some other environments also support the use of "configure". PCRE is written in
Standard C, but there are a few non-standard things it can cope with, allowing
it to run on SunOS4 and other "close to standard" systems.

If you are going to build PCRE "by hand" on a system without "configure" you
should copy the distributed config.h.generic to config.h, and then set up the
macro definitions the way you need them. You must then add -DHAVE_CONFIG_H to
all of your compile commands, so that config.h is included at the start of
every source.

Alternatively, you can avoid editing by using -D on the compiler command line
to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H.

PCRE uses memmove() if HAVE_MEMMOVE is set to 1; otherwise it uses bcopy() if
HAVE_BCOPY is set to 1. If your system has neither bcopy() nor memmove(), set
them both to 0; an emulation function will be used. */

/* By default, the \R escape sequence matches any Unicode line ending
   character or sequence of characters. If BSR_ANYCRLF is defined, this is
   changed so that backslash-R matches only CR, LF, or CRLF. The build- time
   default can be overridden by the user of PCRE at runtime. On systems that
   support it, "configure" can be used to override the default. */
/* #undef BSR_ANYCRLF */

/* If you are compiling for a system that uses EBCDIC instead of ASCII
   character codes, define this macro as 1. On systems that can use
   "configure", this can be done via --enable-ebcdic. PCRE will then assume
   that all input strings are in EBCDIC. If you do not define this macro, PCRE
   will assume input strings are ASCII or UTF-8/16 Unicode. It is not possible
   to build a version of PCRE that supports both EBCDIC and UTF-8/16. */
#undef EBCDIC
/* ZA - define EBCDIC for native z/OS */
#ifndef EBCDIC
#define EBCDIC 1
#endif

/* Define to 1 if you have the `bcopy' function. */
#ifndef HAVE_BCOPY
#define HAVE_BCOPY 1
#endif

/* Define to 1 if you have the <bits/type_traits.h> header file. */
/* #undef HAVE_BITS_TYPE_TRAITS_H */

/* Define to 1 if you have the <bzlib.h> header file. */
#ifndef HAVE_BZLIB_H
#define HAVE_BZLIB_H 1
#endif

/* Define to 1 if you have the <dirent.h> header file. */
/* ZA - not available in z/OS*/
/*
#ifndef HAVE_DIRENT_H
#define HAVE_DIRENT_H 1
#endif
*/

/* Define to 1 if you have the <dlfcn.h> header file. */
#ifndef HAVE_DLFCN_H
#define HAVE_DLFCN_H 1
#endif

/* Define to 1 if you have the <editline/readline.h> header file. */
/* #undef HAVE_EDITLINE_READLINE_H */

/* Define to 1 if you have the <edit/readline/readline.h> header file. */
/* #undef HAVE_EDIT_READLINE_READLINE_H */

/* Define to 1 if you have the <inttypes.h> header file. */
#ifndef HAVE_INTTYPES_H
#define HAVE_INTTYPES_H 1
#endif

/* Define to 1 if you have the <limits.h> header file. */
#ifndef HAVE_LIMITS_H
#define HAVE_LIMITS_H 1
#endif

/* Define to 1 if the system has the type `long long'. */
#ifndef HAVE_LONG_LONG
#define HAVE_LONG_LONG 1
#endif

/* Define to 1 if you have the `memmove' function. */
#ifndef HAVE_MEMMOVE
#define HAVE_MEMMOVE 1
#endif

/* Define to 1 if you have the <memory.h> header file. */
#ifndef HAVE_MEMORY_H
#define HAVE_MEMORY_H 1
#endif

/* Define to 1 if you have the <readline/history.h> header file. */
/* #undef HAVE_READLINE_HISTORY_H */

/* Define to 1 if you have the <readline/readline.h> header file. */
/* #undef HAVE_READLINE_READLINE_H */

/* Define to 1 if you have the <stdint.h> header file. */
/* ZA - not available in z/OS*/
/*
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H 1
#endif
*/

/* Define to 1 if you have the <stdlib.h> header file. */
#ifndef HAVE_STDLIB_H
#define HAVE_STDLIB_H 1
#endif

/* Define to 1 if you have the `strerror' function. */
#ifndef HAVE_STRERROR
#define HAVE_STRERROR 1
#endif

/* Define to 1 if you have the <string> header file. */
#ifndef HAVE_STRING
#define HAVE_STRING 1
#endif

/* Define to 1 if you have the <strings.h> header file. */
#ifndef HAVE_STRINGS_H
#define HAVE_STRINGS_H 1
#endif

/* Define to 1 if you have the <string.h> header file. */
#ifndef HAVE_STRING_H
#define HAVE_STRING_H 1
#endif

/* Define to 1 if you have `strtoimax'. */
/* #undef HAVE_STRTOIMAX */

/* Define to 1 if you have `strtoll'. */
/* #undef HAVE_STRTOLL */

/* Define to 1 if you have `strtoq'. */
#ifndef HAVE_STRTOQ
#define HAVE_STRTOQ 1
#endif

/* Define to 1 if you have the <sys/stat.h> header file. */
#ifndef HAVE_SYS_STAT_H
#define HAVE_SYS_STAT_H 1
#endif

/* Define to 1 if you have the <sys/types.h> header file. */
#ifndef HAVE_SYS_TYPES_H
#define HAVE_SYS_TYPES_H 1
#endif

/* Define to 1 if you have the <type_traits.h> header file. */
/* #undef HAVE_TYPE_TRAITS_H */

/* Define to 1 if you have the <unistd.h> header file. */
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
#endif

/* Define to 1 if the system has the type `unsigned long long'. */
#ifndef HAVE_UNSIGNED_LONG_LONG
#define HAVE_UNSIGNED_LONG_LONG 1
#endif

/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */

/* Define to 1 if you have the <zlib.h> header file. */
#ifndef HAVE_ZLIB_H
#define HAVE_ZLIB_H 1
#endif

/* Define to 1 if you have `_strtoi64'. */
/* #undef HAVE__STRTOI64 */

/* The value of LINK_SIZE determines the number of bytes used to store links
   as offsets within the compiled regex. The default is 2, which allows for
   compiled patterns up to 64K long. This covers the vast majority of cases.
   However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows
   for longer patterns in extreme cases. On systems that support it,
   "configure" can be used to override this default. */
#ifndef LINK_SIZE
#define LINK_SIZE 2
#endif

/* Define to the sub-directory in which libtool stores uninstalled libraries.
   */
#ifndef LT_OBJDIR
#define LT_OBJDIR ".libs/"
#endif

/* The value of MATCH_LIMIT determines the default number of times the
   internal match() function can be called during a single execution of
   PCREXEC8(). There is a runtime interface for setting a different limit.
   The limit exists in order to catch runaway regular expressions that take
   for ever to determine that they do not match. The default is set very large
   so that it does not accidentally catch legitimate cases. On systems that
   support it, "configure" can be used to override this default default. */
#ifndef MATCH_LIMIT
#define MATCH_LIMIT 10000000
#endif

/* The above limit applies to all calls of match(), whether or not they
   increase the recursion depth. In some environments it is desirable to limit
   the depth of recursive calls of match() more strictly, in order to restrict
   the maximum amount of stack (or heap, if NO_RECURSE is defined) that is
   used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of
   match(). To have any useful effect, it must be less than the value of
   MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is
   a runtime method for setting a different limit. On systems that support it,
   "configure" can be used to override the default. */
#ifndef MATCH_LIMIT_RECURSION
#define MATCH_LIMIT_RECURSION MATCH_LIMIT
#endif

/* This limit is parameterized just in case anybody ever wants to change it.
   Care must be taken if it is increased, because it guards against integer
   overflow caused by enormously large patterns. */
#ifndef MAX_NAME_COUNT
#define MAX_NAME_COUNT 10000
#endif

/* This limit is parameterized just in case anybody ever wants to change it.
   Care must be taken if it is increased, because it guards against integer
   overflow caused by enormously large patterns. */
#ifndef MAX_NAME_SIZE
#define MAX_NAME_SIZE 32
#endif

/* The value of NEWLINE determines the newline character sequence. On systems
   that support it, "configure" can be used to override the default, which is
   10. The possible values are 10 (LF), 13 (CR), 3338 (CRLF), -1 (ANY), or -2
   (ANYCRLF). */
/* ZA - in EBCDIC, newline is definitely x'15' (NL) */
#ifndef NEWLINE
#define NEWLINE 21
#endif

/* PCRE uses recursive function calls to handle backtracking while matching.
   This can sometimes be a problem on systems that have stacks of limited
   size. Define NO_RECURSE to get a version that doesn't use recursion in the
   match() function; instead it creates its own stack by steam using
   pcre_recurse_malloc() to obtain memory from the heap. For more detail, see
   the comments and other stuff just above the match() function. On systems
   that support it, "configure" can be used to set this in the Makefile (use
   --disable-stack-for-recursion). */
/* #undef NO_RECURSE */

/* Name of package */
#define PACKAGE "pcre"

/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""

/* Define to the full name of this package. */
#define PACKAGE_NAME "PCRE"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "PCRE 8.31"

/* 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.31"

/* The value of PCREGREP_BUFSIZE determines the size of buffer used by
   PCREGREP to hold parts of the file it is searching. On systems that support
   it, "configure" can be used to override the default, which is 8192. This is
   also the minimum value. The actual amount of memory used by PCREGREP is
   three times this number, because it allows for the buffering of "before"
   and "after" lines. */
#ifndef PCREGREP_BUFSIZE
#define PCREGREP_BUFSIZE 20480
#endif


/* If you are compiling for a system other than a Unix-like system or
   Win32, and it needs some magic to be inserted before the definition
   of a function that is exported by the library, define this macro to
   contain the relevant magic. If you do not define this macro, it
   defaults to "extern" for a C compiler and "extern C" for a C++
   compiler on non-Win32 systems. This macro apears at the start of
   every exported function that is part of the external API. It does
   not appear on functions that are "external" in the C sense, but
   which are internal to the library. */
/* #undef PCRE_EXP_DEFN */

/* Define if linking statically (TODO: make nice with Libtool) */
/* #undef PCRE_STATIC */

/* When calling PCRE via the POSIX interface, additional working storage is
   required for holding the pointers to capturing substrings because PCRE
   requires three integers per substring, whereas the POSIX interface provides
   only two. If the number of expected substrings is small, the wrapper
   function uses space on the stack, because this is faster than using
   malloc() for each call. The threshold above which the stack is no longer
   used is defined by POSIX_MALLOC_THRESHOLD. On systems that support it,
   "configure" can be used to override this default. */
#ifndef POSIX_MALLOC_THRESHOLD
#define POSIX_MALLOC_THRESHOLD 10
#endif

/* Define to 1 if you have the ANSI C header files. */
#ifndef STDC_HEADERS
#define STDC_HEADERS 1
#endif

/* Define to enable support for Just-In-Time compiling. */
/* #undef SUPPORT_JIT */

/* Define to allow PCREGREP to be linked with libbz2, so that it is able to
   handle .bz2 files. */
/* #undef SUPPORT_LIBBZ2 */

/* Define to allow PCRETEST to be linked with libedit. */
/* #undef SUPPORT_LIBEDIT */

/* Define to allow PCRETEST to be linked with libreadline. */
/* #undef SUPPORT_LIBREADLINE */

/* Define to allow PCREGREP to be linked with libz, so that it is able to
   handle .gz files. */
/* #undef SUPPORT_LIBZ */

/* Define to enable the 16 bit PCRE library. */
/* #undef SUPPORT_PCRE16 */

/* Define to enable the 8 bit PCRE library. */
#ifndef SUPPORT_PCRE8
#define SUPPORT_PCRE8 /**/
#endif

/* Define to enable JIT support in PCREGREP. */
/* #undef SUPPORT_PCREGREP_JIT */

/* Define to enable support for Unicode properties. */
/* #undef SUPPORT_UCP */

/* Define to enable support for the UTF-8/16 Unicode encoding. This will work
   even in an EBCDIC environment, but it is incompatible with the EBCDIC
   macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16,
   but not both at once. */
/* ZA - no UTF, EBCDIC is required for native z/OS*/
#undef SUPPORT_UTF

/* Version number of package */
#ifndef VERSION
#define VERSION "8.31"
#endif

/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */

/* Define to the type of a signed integer type of width exactly 64 bits if
   such a type exists and the standard includes do not define it. */
/* #undef int64_t */

/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/*autoconv-0001 C:\projects\pcreport\config.h converted to CONFIG*/
/*autoconv-0013 CONFIG line: 237 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 CONFIG line: 314 pcregrep replaced by PCREGREP*/
/*autoconv-0013 CONFIG line: 316 pcregrep replaced by PCREGREP*/
/*autoconv-0013 CONFIG line: 358 pcregrep replaced by PCREGREP*/
/*autoconv-0013 CONFIG line: 362 pcretest replaced by PCRETEST*/
/*autoconv-0013 CONFIG line: 365 pcretest replaced by PCRETEST*/
/*autoconv-0013 CONFIG line: 368 pcregrep replaced by PCREGREP*/
/*autoconv-0013 CONFIG line: 380 pcregrep replaced by PCREGREP*/
./ ADD NAME=PRINTIN8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains a PCRE private debugging function for printing out the
internal form of a compiled regular expression, along with some supporting
local functions. This source file is used in two places:

(1) It is #included by COMPILE8.c when it is compiled in debugging mode
(PCRE_DEBUG defined in pcre_internal.h). It is not included in production
compiles. In this case PCRE_INCLUDED is defined.

(2) It is also compiled separately and linked with PCRETEST.c, which can be
asked to print out a compiled regex for debugging purposes. */

#ifndef PCRE_INCLUDED

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

/* For PCRETEST program. */
#define PRIV(name) name

/* We have to include pcre_internal.h because we need the internal info for
displaying the results of STUDY8() and we also need to know about the
internal macros, structures, and other internal data values; PCRETEST has
"inside information" compared to a program that strictly follows the PCRE API.

Although pcre_internal.h does itself include pcre.h, we explicitly include it
here before pcre_internal.h so that the PCRE_EXP_xxx macros get set
appropriately for an application, not for building PCRE. */

#include "PCRE.h"
#include "INTERNA8.h"

/* These are the funtions that are contained within. It doesn't seem worth
having a separate .h file just for this. */

#endif /* PCRE_INCLUDED */

#ifdef PCRE_INCLUDED
static /* Keep the following function as private. */
#endif
#ifdef COMPILE_PCRE8
void PRINTIN8(pcre *external_re, FILE *f, BOOL print_lengths);
#else
void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths);
#endif

/* Macro that decides whether a character should be output as a literal or in
hexadecimal. We don't use isprint() because that can vary from system to system
(even without the use of locales) and we want the output always to be the same,
for testing purposes. */

#ifdef EBCDIC
#define PRINTABLE(c) ((c) >= 64 && (c) < 255)
#else
#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
#endif

/* The table of operator names. */

static const char *priv_OP_names[] = { OP_NAME_LIST };

/* This table of operator lengths is not actually used by the working code,
but its size is needed for a check that ensures it is the correct size for the
number of opcodes (thus catching update omissions). */

static const pcre_uint8 priv_OP_lengths[] = { OP_LENGTHS };



/*************************************************
*       Print single- or multi-byte character    *
*************************************************/

static int
print_char(FILE *f, pcre_uchar *ptr, BOOL utf)
{
int c = *ptr;

#ifndef SUPPORT_UTF

(void)utf;  /* Avoid compiler warning */
if (PRINTABLE(c)) fprintf(f, "%c", c);
else if (c <= 0xff) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%x}", c);
return 0;

#else

#ifdef COMPILE_PCRE8

if (!utf || (c & 0xc0) != 0xc0)
  {
  if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c);
  return 0;
  }
else
  {
  int i;
  int a = PRIV(utf8_table4)[c & 0x3f];  /* Number of additional bytes */
  int s = 6*a;
  c = (c & PRIV(utf8_table3)[a]) << s;
  for (i = 1; i <= a; i++)
    {
    /* This is a check for malformed UTF-8; it should only occur if the sanity
    check has been turned off. Rather than swallow random bytes, just stop if
    we hit a bad one. Print it with \X instead of \x as an indication. */

    if ((ptr[i] & 0xc0) != 0x80)
      {
      fprintf(f, "\\X{%x}", c);
      return i - 1;
      }

    /* The byte is OK */

    s -= 6;
    c |= (ptr[i] & 0x3f) << s;
    }
  fprintf(f, "\\x{%x}", c);
  return a;
  }

#else

#ifdef COMPILE_PCRE16

if (!utf || (c & 0xfc00) != 0xd800)
  {
  if (PRINTABLE(c)) fprintf(f, "%c", c);
  else if (c <= 0xff) fprintf(f, "\\x%02x", c);
  else fprintf(f, "\\x{%x}", c);
  return 0;
  }
else
  {
  /* This is a check for malformed UTF-16; it should only occur if the sanity
  check has been turned off. Rather than swallow a low surrogate, just stop if
  we hit a bad one. Print it with \X instead of \x as an indication. */

  if ((ptr[1] & 0xfc00) != 0xdc00)
    {
    fprintf(f, "\\X{%x}", c);
    return 0;
    }

  c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;
  fprintf(f, "\\x{%x}", c);
  return 1;
  }

#endif /* COMPILE_PCRE16 */

#endif /* COMPILE_PCRE8 */

#endif /* SUPPORT_UTF */
}

/*************************************************
*  Print uchar string (regardless of utf)        *
*************************************************/

static void
print_puchar(FILE *f, PCRE_PUCHAR ptr)
{
while (*ptr != '\0')
  {
  register int c = *ptr++;
  if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
  }
}

/*************************************************
*          Find Unicode property name            *
*************************************************/

static const char *
get_ucpname(int ptype, int pvalue)
{
#ifdef SUPPORT_UCP
int i;
for (i = PRIV(utt_size) - 1; i >= 0; i--)
  {
  if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;
  }
return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";
#else
/* It gets harder and harder to shut off unwanted compiler warnings. */
ptype = ptype * pvalue;
return (ptype == pvalue)? "??" : "??";
#endif
}



/*************************************************
*         Print compiled regex                   *
*************************************************/

/* Make this function work for a regex with integers either byte order.
However, we assume that what we are passed is a compiled regex. The
print_lengths flag controls whether offsets and lengths of items are printed.
They can be turned off from PCRETEST so that automatic tests on bytecode can be
written that do not depend on the value of LINK_SIZE. */

#ifdef PCRE_INCLUDED
static /* Keep the following function as private. */
#endif
#ifdef COMPILE_PCRE8
void
PRINTIN8(pcre *external_re, FILE *f, BOOL print_lengths)
#else
void
pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)external_re;
pcre_uchar *codestart, *code;
BOOL utf;

unsigned int options = re->options;
int offset = re->name_table_offset;
int count = re->name_count;
int size = re->name_entry_size;

if (re->magic_number != MAGIC_NUMBER)
  {
  offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff);
  count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff);
  size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff);
  options = ((options << 24) & 0xff000000) |
            ((options <<  8) & 0x00ff0000) |
            ((options >>  8) & 0x0000ff00) |
            ((options >> 24) & 0x000000ff);
  }

code = codestart = (pcre_uchar *)re + offset + count * size;
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
utf = (options & PCRE_UTF8) != 0;

for(;;)
  {
  pcre_uchar *ccode;
  const char *flag = "  ";
  int c;
  int extra = 0;

  if (print_lengths)
    fprintf(f, "%3d ", (int)(code - codestart));
  else
    fprintf(f, "    ");

  switch(*code)
    {
/* ========================================================================== */
      /* These cases are never obeyed. This is a fudge that causes a compile-
      time error if the vectors OP_names or OP_lengths, which are indexed
      by opcode, are not the correct length. It seems to be the only way to do
      such a check at compile time, as the sizeof() operator does not work in
      the C preprocessor. */

      case OP_TABLE_LENGTH:
      case OP_TABLE_LENGTH +
        ((sizeof(priv_OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
        (sizeof(priv_OP_lengths) == OP_TABLE_LENGTH)):
      break;
/* ========================================================================== */

    case OP_END:
    fprintf(f, "    %s\n", priv_OP_names[*code]);
    fprintf(f, "------------------------------------------------------------------\n");
    return;

    case OP_CHAR:
    fprintf(f, "    ");
    do
      {
      code++;
      code += 1 + print_char(f, code, utf);
      }
    while (*code == OP_CHAR);
    fprintf(f, "\n");
    continue;

    case OP_CHARI:
    fprintf(f, " /i ");
    do
      {
      code++;
      code += 1 + print_char(f, code, utf);
      }
    while (*code == OP_CHARI);
    fprintf(f, "\n");
    continue;

    case OP_CBRA:
    case OP_CBRAPOS:
    case OP_SCBRA:
    case OP_SCBRAPOS:
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
      else fprintf(f, "    ");
    fprintf(f, "%s %d", priv_OP_names[*code], GET2(code, 1+LINK_SIZE));
    break;

    case OP_BRA:
    case OP_BRAPOS:
    case OP_SBRA:
    case OP_SBRAPOS:
    case OP_KETRMAX:
    case OP_KETRMIN:
    case OP_KETRPOS:
    case OP_ALT:
    case OP_KET:
    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_COND:
    case OP_SCOND:
    case OP_REVERSE:
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
      else fprintf(f, "    ");
    fprintf(f, "%s", priv_OP_names[*code]);
    break;

    case OP_CLOSE:
    fprintf(f, "    %s %d", priv_OP_names[*code], GET2(code, 1));
    break;

    case OP_CREF:
    case OP_NCREF:
    fprintf(f, "%3d %s", GET2(code,1), priv_OP_names[*code]);
    break;

    case OP_RREF:
    c = GET2(code, 1);
    if (c == RREF_ANY)
      fprintf(f, "    Cond recurse any");
    else
      fprintf(f, "    Cond recurse %d", c);
    break;

    case OP_NRREF:
    c = GET2(code, 1);
    if (c == RREF_ANY)
      fprintf(f, "    Cond nrecurse any");
    else
      fprintf(f, "    Cond nrecurse %d", c);
    break;

    case OP_DEF:
    fprintf(f, "    Cond def");
    break;

    case OP_STARI:
    case OP_MINSTARI:
    case OP_POSSTARI:
    case OP_PLUSI:
    case OP_MINPLUSI:
    case OP_POSPLUSI:
    case OP_QUERYI:
    case OP_MINQUERYI:
    case OP_POSQUERYI:
    flag = "/i";
    /* Fall through */
    case OP_STAR:
    case OP_MINSTAR:
    case OP_POSSTAR:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_POSPLUS:
    case OP_QUERY:
    case OP_MINQUERY:
    case OP_POSQUERY:
    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEPOSSTAR:
    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEPOSPLUS:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    case OP_TYPEPOSQUERY:
    fprintf(f, " %s ", flag);
    if (*code >= OP_TYPESTAR)
      {
      fprintf(f, "%s", priv_OP_names[code[1]]);
      if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
        {
        fprintf(f, " %s ", get_ucpname(code[2], code[3]));
        extra = 2;
        }
      }
    else extra = print_char(f, code+1, utf);
    fprintf(f, "%s", priv_OP_names[*code]);
    break;

    case OP_EXACTI:
    case OP_UPTOI:
    case OP_MINUPTOI:
    case OP_POSUPTOI:
    flag = "/i";
    /* Fall through */
    case OP_EXACT:
    case OP_UPTO:
    case OP_MINUPTO:
    case OP_POSUPTO:
    fprintf(f, " %s ", flag);
    extra = print_char(f, code + 1 + IMM2_SIZE, utf);
    fprintf(f, "{");
    if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
    fprintf(f, "%d}", GET2(code,1));
    if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
      else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
    break;

    case OP_TYPEEXACT:
    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    case OP_TYPEPOSUPTO:
    fprintf(f, "    %s", priv_OP_names[code[1 + IMM2_SIZE]]);
    if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
      {
      fprintf(f, " %s ", get_ucpname(code[1 + IMM2_SIZE + 1],
        code[1 + IMM2_SIZE + 2]));
      extra = 2;
      }
    fprintf(f, "{");
    if (*code != OP_TYPEEXACT) fprintf(f, "0,");
    fprintf(f, "%d}", GET2(code,1));
    if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
      else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
    break;

    case OP_NOTI:
    flag = "/i";
    /* Fall through */
    case OP_NOT:
    fprintf(f, " %s [", flag);
    extra = print_char(f, code + 1, utf);
    fprintf(f, "]");
    break;

    case OP_NOTSTARI:
    case OP_NOTMINSTARI:
    case OP_NOTPOSSTARI:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUSI:
    case OP_NOTPOSPLUSI:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERYI:
    case OP_NOTPOSQUERYI:
    flag = "/i";
    /* Fall through */

    case OP_NOTSTAR:
    case OP_NOTMINSTAR:
    case OP_NOTPOSSTAR:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTPOSPLUS:
    case OP_NOTQUERY:
    case OP_NOTMINQUERY:
    case OP_NOTPOSQUERY:
    fprintf(f, " %s [", flag);
    extra = print_char(f, code + 1, utf);
    fprintf(f, "]%s", priv_OP_names[*code]);
    break;

    case OP_NOTEXACTI:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTOI:
    case OP_NOTPOSUPTOI:
    flag = "/i";
    /* Fall through */

    case OP_NOTEXACT:
    case OP_NOTUPTO:
    case OP_NOTMINUPTO:
    case OP_NOTPOSUPTO:
    fprintf(f, " %s [", flag);
    extra = print_char(f, code + 1 + IMM2_SIZE, utf);
    fprintf(f, "]{");
    if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
    fprintf(f, "%d}", GET2(code,1));
    if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
      else
    if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
    break;

    case OP_RECURSE:
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
      else fprintf(f, "    ");
    fprintf(f, "%s", priv_OP_names[*code]);
    break;

    case OP_REFI:
    flag = "/i";
    /* Fall through */
    case OP_REF:
    fprintf(f, " %s \\%d", flag, GET2(code,1));
    ccode = code + priv_OP_lengths[*code];
    goto CLASS_REF_REPEAT;

    case OP_CALLOUT:
    fprintf(f, "    %s %d %d %d", priv_OP_names[*code], code[1], GET(code,2),
      GET(code, 2 + LINK_SIZE));
    break;

    case OP_PROP:
    case OP_NOTPROP:
    fprintf(f, "    %s %s", priv_OP_names[*code], get_ucpname(code[1], code[2]));
    break;

    /* OP_XCLASS can only occur in UTF or PCRE16 modes. However, there's no
    harm in having this code always here, and it makes it less messy without
    all those #ifdefs. */

    case OP_CLASS:
    case OP_NCLASS:
    case OP_XCLASS:
      {
      int i, min, max;
      BOOL printmap;
      pcre_uint8 *map;

      fprintf(f, "    [");

      if (*code == OP_XCLASS)
        {
        extra = GET(code, 1);
        ccode = code + LINK_SIZE + 1;
        printmap = (*ccode & XCL_MAP) != 0;
        if ((*ccode++ & XCL_NOT) != 0) fprintf(f, "");
        }
      else
        {
        printmap = TRUE;
        ccode = code + 1;
        }

      /* Print a bit map */

      if (printmap)
        {
        map = (pcre_uint8 *)ccode;
        for (i = 0; i < 256; i++)
          {
          if ((map[i/8] & (1 << (i&7))) != 0)
            {
            int j;
            for (j = i+1; j < 256; j++)
              if ((map[j/8] & (1 << (j&7))) == 0) break;
            if (i == '-' || i == ']') fprintf(f, "\\");
            if (PRINTABLE(i)) fprintf(f, "%c", i);
              else fprintf(f, "\\x%02x", i);
            if (--j > i)
              {
              if (j != i + 1) fprintf(f, "-");
              if (j == '-' || j == ']') fprintf(f, "\\");
              if (PRINTABLE(j)) fprintf(f, "%c", j);
                else fprintf(f, "\\x%02x", j);
              }
            i = j;
            }
          }
        ccode += 32 / sizeof(pcre_uchar);
        }

      /* For an XCLASS there is always some additional data */

      if (*code == OP_XCLASS)
        {
        int ch;
        while ((ch = *ccode++) != XCL_END)
          {
          if (ch == XCL_PROP)
            {
            int ptype = *ccode++;
            int pvalue = *ccode++;
            fprintf(f, "\\p{%s}", get_ucpname(ptype, pvalue));
            }
          else if (ch == XCL_NOTPROP)
            {
            int ptype = *ccode++;
            int pvalue = *ccode++;
            fprintf(f, "\\P{%s}", get_ucpname(ptype, pvalue));
            }
          else
            {
            ccode += 1 + print_char(f, ccode, utf);
            if (ch == XCL_RANGE)
              {
              fprintf(f, "-");
              ccode += 1 + print_char(f, ccode, utf);
              }
            }
          }
        }

      /* Indicate a non-UTF class which was created by negation */

      fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");

      /* Handle repeats after a class or a back reference */

      CLASS_REF_REPEAT:
      switch(*ccode)
        {
        case OP_CRSTAR:
        case OP_CRMINSTAR:
        case OP_CRPLUS:
        case OP_CRMINPLUS:
        case OP_CRQUERY:
        case OP_CRMINQUERY:
        fprintf(f, "%s", priv_OP_names[*ccode]);
        extra += priv_OP_lengths[*ccode];
        break;

        case OP_CRRANGE:
        case OP_CRMINRANGE:
        min = GET2(ccode,1);
        max = GET2(ccode,1 + IMM2_SIZE);
        if (max == 0) fprintf(f, "{%d,}", min);
        else fprintf(f, "{%d,%d}", min, max);
        if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
        extra += priv_OP_lengths[*ccode];
        break;

        /* Do nothing if it's not a repeat; this code stops picky compilers
        warning about the lack of a default code path. */

        default:
        break;
        }
      }
    break;

    case OP_MARK:
    case OP_PRUNE_ARG:
    case OP_SKIP_ARG:
    case OP_THEN_ARG:
    fprintf(f, "    %s ", priv_OP_names[*code]);
    print_puchar(f, code + 2);
    extra += code[1];
    break;

    case OP_THEN:
    fprintf(f, "    %s", priv_OP_names[*code]);
    break;

    case OP_CIRCM:
    case OP_DOLLM:
    flag = "/m";
    /* Fall through */

    /* Anything else is just an item with no data, but possibly a flag. */

    default:
    fprintf(f, " %s %s", flag, priv_OP_names[*code]);
    break;
    }

  code += priv_OP_lengths[*code] + extra;
  fprintf(f, "\n");
  }
}

/* End of PRINTIN8.src */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_printint.c converted to PRINTIN8*/
/*autoconv-0013 PRINTIN8 line: 45 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PRINTIN8 line: 49 pcretest replaced by PCRETEST*/
/*autoconv-0010 PRINTIN8 line: 55 added HAVE_CONFIG_H*/
/*autoconv-0011 PRINTIN8 line: 58 config.h replaced by CONFIG.h*/
/*autoconv-0013 PRINTIN8 line: 61 pcretest replaced by PCRETEST*/
/*autoconv-0013 PRINTIN8 line: 65 pcre_study replaced by STUDY8*/
/*autoconv-0013 PRINTIN8 line: 66 pcretest replaced by PCRETEST*/
/*autoconv-0011 PRINTIN8 line: 73 pcre.h replaced by PCRE.h*/
/*autoconv-0011 PRINTIN8 line: 74 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 PRINTIN8 line: 85 pcre_printint replaced by PRINTIN8*/
/*autoconv-0013 PRINTIN8 line: 245 pcretest replaced by PCRETEST*/
/*autoconv-0013 PRINTIN8 line: 253 pcre_printint replaced by PRINTIN8*/
/*autoconv-0013 PRINTIN8 line: 713 pcre_printint replaced by PRINTIN8*/
./ ADD NAME=PCRZFUNC 
#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#ifdef NATIVE_ZOS
#include "pcre.h"
#include "interna8.h"

#ifndef CHAR_NULL
#define CHAR_NULL 0x00
#endif
#define NULL_TERMINATED -1
#define SPACE_TERMINATED -2
#define LENGTH_TERMINATED -3
/*
THE z/OS specific functionality
-------------------------------

Contributed by:   Ze'ev Atlas.

Copyright (c) 2012, Ze'ev Atlas.
All rights reserved.


THE "BSD" LICENCE
-----------------

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the name of Google
      Inc. nor the names of their contributors may be used to endorse or
      promote products derived from this software without specific prior
      written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.                                          */

/* The functions herein do not use Reg Exp because Reg Exp is not yet
available.  They help to prepare COBOL fixed length character strings for Reg
Exp manipulation.  COBOL character strings are fundamentally different then C
(and thus also C++, Java, C# and virtually any other language) character
strings in that they are fixed length or length terminated (i.e. the length of
the string is known either in compile time or in run time via some variable.)
That length is retrievable by means of querying the prefix variable or using
the LENGTH OF special register.  There is no terminator character (null or
otherwise.)  COBOL notion of fixed length or length terminated character
strings relate directly to the notion of fixed length records - record length
is pre-defined and known in similar manner and there is no record terminator
character.
Most other languages use the null terminated notation (i.e. the end-of-string
is signaled by the null character.  Regular Expression as defined and implemented
by Perl, Posix and PCRE depend on the string being null terminated.
To add to the complication, C on z/OS adds record terminator to the end of the
record even on fixed length records, but on text records, at least from the
standard input, the last spaces are chopped.  I coined that type as space
terminated records and strings.
The functions herein provide the means to query a character string and convert
it to the desired format.
Currently, these functions compile only under NATIVE_ZOS as I suspect that nobody
else will want or need them, however, it is pretty simple to remove this
limitation                                                                     */

PCRE_EXP_DECL int pcrz_what_term_str (char * str, int maxlen);
PCRE_EXP_DECL int pcrz_is_space_term_str (char * str, int maxlen);
PCRE_EXP_DECL int pcrz_is_null_term_str (char * str, int maxlen);
PCRE_EXP_DECL int pcrz_space_to_null_term_str (char * str, int maxlen);
PCRE_EXP_DECL int pcrz_null_to_space_term_str (char * str, int maxlen);
/* to make a length terminated into null terminated use COBOL (or PL/I
equivalent) technique of concatenating the sting with null:
           STRING YOUR-LENGTH-TERMINATED_STRING, LOW-VALUE
                  DELIMITED BY SIZE INTO YOUR-TARGET-STRING
*/

/* This function examines the presumably COBOL character string as is.  If it
is not null terminated, then if there is at least one space in the end it will
return -2 for space terminated and if the last character is not space it will
return -3 for length terminated.  The user may disregard the difference between
length and space terminated, depending on the application.  If the string is
null  terminated, then the function will return -1.
Note: maxlen is one more then the null terminated string length to allow for
the null terminator.  For the others it is the fixed length of the string.  */
int pcrz_what_term_str (char * str, int maxlen)
{
   int i;
   /* is it null terminated? */
   for (i=0; i<maxlen; i++)
   {
      if (str [i] == CHAR_NULL)
      {
         return NULL_TERMINATED; /* null terminated */
      }
   }
   /* no! then choose among length terminated variants*/
   if (str [maxlen-1] ==  CHAR_SPACE)
   {
      return SPACE_TERMINATED; /*space terminated*/
   }
   else
   {
      return LENGTH_TERMINATED;  /*length terminated */
   }
}

/* This function examines the presumably COBOL character string as is.  If it
is not null terminated, then it looks for the last non-space character and
returns the actual length of the string to that character.  If the last
character is not space it will return -3 for length terminated.  If the string
is null terminated, then the function will return -1                        */
int pcrz_is_space_term_str (char * str, int maxlen)
{
   int i;
   for (i=0; i<maxlen; i++)
   {
      if (str [i] == CHAR_NULL)
      {
         return NULL_TERMINATED; /* no, it is null terminated */
      }
   }
   for (i=maxlen-1; i>=0; i--)
   {
      if (str [i] !=  CHAR_SPACE)
      {
         return i+1; /* length of spaec terminated */
      }
   }
   return LENGTH_TERMINATED;  /*length terminated */
}

/* This function examines the presumably COBOL character string as is.  If it
is null terminated then its length is returned.  Otherewise, if there is at
least one space in the end it will return -2 for space terminated and if the
last character is not space it will return -3 for length terminated.  The user
may disregard the difference between length and space terminated, depending on
the application.
Note: maxlen is one more then the null terminated string length to allow for
the null terminator.  For the others it is the fixed length of the string.  */
int pcrz_is_null_term_str (char * str, int maxlen)
{
   int i;
   for (i=0; i<maxlen; i++)
   {
      if (str [i] == CHAR_NULL)
      {
         return i; /* length of null terminated */
      }
   }
   /* no! tehn choose among length terminated variants*/
   if (str [maxlen-1] ==  CHAR_SPACE)
   {
      return SPACE_TERMINATED; /*space terminated*/
   }
   else
   {
      return LENGTH_TERMINATED;  /*length terminated */
   }
}

/* This function examines the presumably COBOL character string.  If it is
already null terminated, only the null terminated string part is examined
farther.  The function then looks for the last non-space character, marks the
next character as null and returns the actual length of the null terminated
string.  If the last non-space character is the last character (no room for
null character, then the function will return -3 for length terminated.
Note: maxlen is one more then the null terminated string length to allow for
the null terminator.  For the others it is the fixed length of the string.  */
int pcrz_space_to_null_term_str (char * str, int maxlen)
{
   int i;
   int j;
   j = maxlen;
   for (i=0; i<maxlen; i++)
   {
      if (str [i] == CHAR_NULL)
      {
         j= i;
         break;
      }
   }
   for (i=j-1; i>=0; i--)
   {
      if (str [i] !=  CHAR_SPACE)
      {
         if (i+1 == maxlen)
         {
            return LENGTH_TERMINATED; /*length terminated */
         }
         else
         {
            str [i+1] = CHAR_NULL;
            return i; /* length of spaec terminated */
         }
      }
   }
}

/* This function examines the presumably COBOL character string.  If it is null
terminated, the null character and all characters after it to maxlen are
replaced by space.  The function then looks for the last non-space character
and returns the actual length of the space terminated string.  If the last
non-space character is the last character, then the function will return -3 for
length terminated.
Note: maxlen is one more then the null terminated string length to allow for
the null terminator.  For the others it is the fixed length of the string.  */
int pcrz_null_to_space_term_str (char * str, int maxlen)
{
   int i;
   int j;
   for (i=0; i<maxlen; i++)
   {
      if (str [i] == CHAR_NULL)
      {
         for (j=1; j < maxlen; j++)
         {
            str [j] =  CHAR_SPACE;
         }
      }
   }
   if (str [maxlen - 1] !=  CHAR_SPACE)
   {
      return LENGTH_TERMINATED;  /*length terminated */
   }
   for (i=maxlen-1; i>=0; i--)
   {
      if (str [i] !=  CHAR_SPACE)
      {
          return i; /* length of spaec terminated */
      }
   }
}
#endif
/*autoconv-0001 C:\projects\pcreport\pcrzfunc.c converted to PCRZFUNC*/
./ ADD NAME=SCANNECC 
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Greg J. Badros
//
// Unittest for scanner, especially GetNextComments and GetComments()
// functionality.

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <stdio.h>
#include <string.h>      /* for strchr */
#include <string>
#include <vector>

#include "CPPH.h"
#include "pcre_stringpiece.h"
#include "SCANNERH.h"

#define FLAGS_unittest_stack_size   49152

// Dies with a fatal error if the two values are not equal.
#define CHECK_EQ(a, b)  do {                                    \
  if ( (a) != (b) ) {                                           \
    fprintf(stderr, "%s:%d: Check failed because %s != %s\n",   \
            __FILE__, __LINE__, #a, #b);                        \
    exit(1);                                                    \
  }                                                             \
} while (0)

using std::vector;
using PCRECPP::StringPiece;
using PCRECPP::Scanner;

static void TestScanner() {
  const char input[] = "\n"
                       "alpha = 1; // this sets alpha\n"
                       "bravo = 2; // bravo is set here\n"
                       "gamma = 33; /* and here is gamma */\n";

  const char *re = "(\\w+) = (\\d+);";

  Scanner s(input);
  string var;
  int number;
  s.SkipCXXComments();
  s.set_save_comments(true);
  vector<StringPiece> comments;

  s.Consume(re, &var, &number);
  CHECK_EQ(var, "alpha");
  CHECK_EQ(number, 1);
  CHECK_EQ(s.LineNumber(), 3);
  s.GetNextComments(&comments);
  CHECK_EQ(comments.size(), 1);
  CHECK_EQ(comments[0].as_string(), " // this sets alpha\n");
  comments.resize(0);

  s.Consume(re, &var, &number);
  CHECK_EQ(var, "bravo");
  CHECK_EQ(number, 2);
  s.GetNextComments(&comments);
  CHECK_EQ(comments.size(), 1);
  CHECK_EQ(comments[0].as_string(), " // bravo is set here\n");
  comments.resize(0);

  s.Consume(re, &var, &number);
  CHECK_EQ(var, "gamma");
  CHECK_EQ(number, 33);
  s.GetNextComments(&comments);
  CHECK_EQ(comments.size(), 1);
  CHECK_EQ(comments[0].as_string(), " /* and here is gamma */\n");
  comments.resize(0);

  s.GetComments(0, sizeof(input), &comments);
  CHECK_EQ(comments.size(), 3);
  CHECK_EQ(comments[0].as_string(), " // this sets alpha\n");
  CHECK_EQ(comments[1].as_string(), " // bravo is set here\n");
  CHECK_EQ(comments[2].as_string(), " /* and here is gamma */\n");
  comments.resize(0);

  s.GetComments(0, (int)(strchr(input, '/') - input), &comments);
  CHECK_EQ(comments.size(), 0);
  comments.resize(0);

  s.GetComments((int)(strchr(input, '/') - input - 1), sizeof(input),
                &comments);
  CHECK_EQ(comments.size(), 3);
  CHECK_EQ(comments[0].as_string(), " // this sets alpha\n");
  CHECK_EQ(comments[1].as_string(), " // bravo is set here\n");
  CHECK_EQ(comments[2].as_string(), " /* and here is gamma */\n");
  comments.resize(0);

  s.GetComments((int)(strchr(input, '/') - input - 1),
                (int)(strchr(input + 1, '\n') - input + 1), &comments);
  CHECK_EQ(comments.size(), 1);
  CHECK_EQ(comments[0].as_string(), " // this sets alpha\n");
  comments.resize(0);
}

static void TestBigComment() {
  string input;
  for (int i = 0; i < 1024; ++i) {
    char buf[1024];  // definitely big enough
    sprintf(buf, "    # Comment %d\n", i);
    input += buf;
  }
  input += "name = value;\n";

  Scanner s(input.c_str());
  s.SetSkipExpression("\\s+|#.*\n");

  string name;
  string value;
  s.Consume("(\\w+) = (\\w+);", &name, &value);
  CHECK_EQ(name, "name");
  CHECK_EQ(value, "value");
}

// TODO: also test scanner and big-comment in a thread with a
//       small stack size

int main(int argc, char** argv) {
  TestScanner();
  TestBigComment();

  // Done
  printf("OK\n");

  return 0;
}
/*autoconv-0001 C:\projects\pcre-8.31\pcre_scanner_unittest.cc converted to SCANNECC*/
/*autoconv-0010 SCANNECC line: 36 added HAVE_CONFIG_H*/
/*autoconv-0011 SCANNECC line: 39 config.h replaced by CONFIG.h*/
/*autoconv-0011 SCANNECC line: 47 pcrecpp.h replaced by CPPH.h*/
/*autoconv-0011 SCANNECC line: 49 pcre_scanner.h replaced by SCANNERH.h*/
/*autoconv-0013 SCANNECC line: 63 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 SCANNECC line: 64 pcrecpp replaced by PCRECPP*/
./ ADD NAME=STRINGU8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains an internal function that is used to match an extended
class. It is used by both PCREXEC8() and pcre_def_exec(). */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

#ifndef COMPILE_PCRE8

/*************************************************
*           Compare string utilities             *
*************************************************/

/* The following two functions compares two strings. Basically an strcmp
for non 8 bit characters.

Arguments:
  str1        first string
  str2        second string

Returns:      0 if both string are equal (like strcmp), 1 otherwise
*/

int
PRIV(strcmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2)
{
pcre_uchar c1;
pcre_uchar c2;

while (*str1 != '\0' || *str2 != '\0')
  {
  c1 = *str1++;
  c2 = *str2++;
  if (c1 != c2)
    return ((c1 > c2) << 1) - 1;
  }
/* Both length and characters must be equal. */
return 0;
}

int
PRIV(strcmp_uc_c8)(const pcre_uchar *str1, const char *str2)
{
const pcre_uint8 *ustr2 = (pcre_uint8 *)str2;
pcre_uchar c1;
pcre_uchar c2;

while (*str1 != '\0' || *ustr2 != '\0')
  {
  c1 = *str1++;
  c2 = (pcre_uchar)*ustr2++;
  if (c1 != c2)
    return ((c1 > c2) << 1) - 1;
  }
/* Both length and characters must be equal. */
return 0;
}

/* The following two functions compares two, fixed length
strings. Basically an strncmp for non 8 bit characters.

Arguments:
  str1        first string
  str2        second string
  num         size of the string

Returns:      0 if both string are equal (like strcmp), 1 otherwise
*/

int
PRIV(strncmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2, unsigned int num)
{
pcre_uchar c1;
pcre_uchar c2;

while (num-- > 0)
  {
  c1 = *str1++;
  c2 = *str2++;
  if (c1 != c2)
    return ((c1 > c2) << 1) - 1;
  }
/* Both length and characters must be equal. */
return 0;
}

int
PRIV(strncmp_uc_c8)(const pcre_uchar *str1, const char *str2, unsigned int num)
{
const pcre_uint8 *ustr2 = (pcre_uint8 *)str2;
pcre_uchar c1;
pcre_uchar c2;

while (num-- > 0)
  {
  c1 = *str1++;
  c2 = (pcre_uchar)*ustr2++;
  if (c1 != c2)
    return ((c1 > c2) << 1) - 1;
  }
/* Both length and characters must be equal. */
return 0;
}

/* The following function returns with the length of
a zero terminated string. Basically an strlen for non 8 bit characters.

Arguments:
  str         string

Returns:      length of the string
*/

unsigned int
PRIV(strlen_uc)(const pcre_uchar *str)
{
unsigned int len = 0;
while (*str++ != 0)
  len++;
return len;
}

#endif /* COMPILE_PCRE8 */

/* End of STRINGU8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_string_utils.c converted to STRINGU8*/
/*autoconv-0013 STRINGU8 line: 42 pcre_exec replaced by PCREXEC8*/
/*autoconv-0010 STRINGU8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 STRINGU8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 STRINGU8 line: 52 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 STRINGU8 line: 171 pcre_string_utils replaced by STRINGU8*/
./ ADD NAME=GLOBALS8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains global variables that are exported by the PCRE library.
PCRE is thread-clean and doesn't use any global variables in the normal sense.
However, it calls memory allocation and freeing functions via the four
indirections below, and it can optionally do callouts, using the fifth
indirection. These values can be changed by the caller, but are shared between
all threads.

For MS Visual Studio and Symbian OS, there are problems in initializing these
variables to non-local functions. In these cases, therefore, an indirection via
a local function is used.

Also, when compiling for Virtual Pascal, things are done differently, and
global variables are not used. */

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

#if defined _MSC_VER || defined  __SYMBIAN32__
static void* LocalPcreMalloc(size_t aSize)
  {
  return malloc(aSize);
  }
static void LocalPcreFree(void* aPtr)
  {
  free(aPtr);
  }
PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = LocalPcreMalloc;
PCRE_EXP_DATA_DEFN void  (*PUBL(free))(void *) = LocalPcreFree;
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc;
PCRE_EXP_DATA_DEFN void  (*PUBL(stack_free))(void *) = LocalPcreFree;
PCRE_EXP_DATA_DEFN int   (*PUBL(callout))(PUBL(callout_block) *) = NULL;

#elif !defined VPCOMPAT
PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc;
PCRE_EXP_DATA_DEFN void  (*PUBL(free))(void *) = free;
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc;
PCRE_EXP_DATA_DEFN void  (*PUBL(stack_free))(void *) = free;
PCRE_EXP_DATA_DEFN int   (*PUBL(callout))(PUBL(callout_block) *) = NULL;
#endif

/* End of GLOBALS8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_globals.c converted to GLOBALS8*/
/*autoconv-0010 GLOBALS8 line: 56 added HAVE_CONFIG_H*/
/*autoconv-0011 GLOBALS8 line: 59 config.h replaced by CONFIG.h*/
/*autoconv-0011 GLOBALS8 line: 62 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 GLOBALS8 line: 87 pcre_globals replaced by GLOBALS8*/
./ ADD NAME=VALIDUT8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains an internal function for validating UTF-8 character
strings. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*         Validate a UTF-8 string                *
*************************************************/

/* This function is called (optionally) at the start of compile or match, to
check that a supposed UTF-8 string is actually valid. The early check means
that subsequent code can assume it is dealing with a valid string. The check
can be turned off for maximum performance, but the consequences of supplying an
invalid string are then undefined.

Originally, this function checked according to RFC 2279, allowing for values in
the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were in
the canonical format. Once somebody had pointed out RFC 3629 to me (it
obsoletes 2279), additional restrictions were applied. The values are now
limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the
subrange 0xd000 to 0xdfff is excluded. However, the format of 5-byte and 6-byte
characters is still checked.

From release 8.13 more information about the details of the error are passed
back in the returned value:

PCRE_UTF8_ERR0   No error
PCRE_UTF8_ERR1   Missing 1 byte at the end of the string
PCRE_UTF8_ERR2   Missing 2 bytes at the end of the string
PCRE_UTF8_ERR3   Missing 3 bytes at the end of the string
PCRE_UTF8_ERR4   Missing 4 bytes at the end of the string
PCRE_UTF8_ERR5   Missing 5 bytes at the end of the string
PCRE_UTF8_ERR6   2nd-byte's two top bits are not 0x80
PCRE_UTF8_ERR7   3rd-byte's two top bits are not 0x80
PCRE_UTF8_ERR8   4th-byte's two top bits are not 0x80
PCRE_UTF8_ERR9   5th-byte's two top bits are not 0x80
PCRE_UTF8_ERR10  6th-byte's two top bits are not 0x80
PCRE_UTF8_ERR11  5-byte character is not permitted by RFC 3629
PCRE_UTF8_ERR12  6-byte character is not permitted by RFC 3629
PCRE_UTF8_ERR13  4-byte character with value > 0x10ffff is not permitted
PCRE_UTF8_ERR14  3-byte character with value 0xd000-0xdfff is not permitted
PCRE_UTF8_ERR15  Overlong 2-byte sequence
PCRE_UTF8_ERR16  Overlong 3-byte sequence
PCRE_UTF8_ERR17  Overlong 4-byte sequence
PCRE_UTF8_ERR18  Overlong 5-byte sequence (won't ever occur)
PCRE_UTF8_ERR19  Overlong 6-byte sequence (won't ever occur)
PCRE_UTF8_ERR20  Isolated 0x80 byte (not within UTF-8 character)
PCRE_UTF8_ERR21  Byte with the illegal value 0xfe or 0xff

Arguments:
  string       points to the string
  length       length of string, or -1 if the string is zero-terminated
  errp         pointer to an error position offset variable

Returns:       = 0    if the string is a valid UTF-8 string
               > 0    otherwise, setting the offset of the bad character
*/

int
PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
{
#ifdef SUPPORT_UTF
register PCRE_PUCHAR p;

if (length < 0)
  {
  for (p = string; *p != 0; p++);
  length = (int)(p - string);
  }

for (p = string; length-- > 0; p++)
  {
  register int ab, c, d;

  c = *p;
  if (c < 128) continue;                /* ASCII character */

  if (c < 0xc0)                         /* Isolated 10xx xxxx byte */
    {
    *erroroffset = (int)(p - string);
    return PCRE_UTF8_ERR20;
    }

  if (c >= 0xfe)                        /* Invalid 0xfe or 0xff bytes */
    {
    *erroroffset = (int)(p - string);
    return PCRE_UTF8_ERR21;
    }

  ab = PRIV(utf8_table4)[c & 0x3f];     /* Number of additional bytes */
  if (length < ab)
    {
    *erroroffset = (int)(p - string);          /* Missing bytes */
    return ab - length;                 /* Codes ERR1 to ERR5 */
    }
  length -= ab;                         /* Length remaining */

  /* Check top bits in the second byte */

  if (((d = *(++p)) & 0xc0) != 0x80)
    {
    *erroroffset = (int)(p - string) - 1;
    return PCRE_UTF8_ERR6;
    }

  /* For each length, check that the remaining bytes start with the 0x80 bit
  set and not the 0x40 bit. Then check for an overlong sequence, and for the
  excluded range 0xd800 to 0xdfff. */

  switch (ab)
    {
    /* 2-byte character. No further bytes to check for 0x80. Check first byte
    for for xx00 000x (overlong sequence). */

    case 1: if ((c & 0x3e) == 0)
      {
      *erroroffset = (int)(p - string) - 1;
      return PCRE_UTF8_ERR15;
      }
    break;

    /* 3-byte character. Check third byte for 0x80. Then check first 2 bytes
      for 1110 0000, xx0x xxxx (overlong sequence) or
          1110 1101, 1010 xxxx (0xd800 - 0xdfff) */

    case 2:
    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
      {
      *erroroffset = (int)(p - string) - 2;
      return PCRE_UTF8_ERR7;
      }
    if (c == 0xe0 && (d & 0x20) == 0)
      {
      *erroroffset = (int)(p - string) - 2;
      return PCRE_UTF8_ERR16;
      }
    if (c == 0xed && d >= 0xa0)
      {
      *erroroffset = (int)(p - string) - 2;
      return PCRE_UTF8_ERR14;
      }
    break;

    /* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2
       bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a
       character greater than 0x0010ffff (f4 8f bf bf) */

    case 3:
    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
      {
      *erroroffset = (int)(p - string) - 2;
      return PCRE_UTF8_ERR7;
      }
    if ((*(++p) & 0xc0) != 0x80)     /* Fourth byte */
      {
      *erroroffset = (int)(p - string) - 3;
      return PCRE_UTF8_ERR8;
      }
    if (c == 0xf0 && (d & 0x30) == 0)
      {
      *erroroffset = (int)(p - string) - 3;
      return PCRE_UTF8_ERR17;
      }
    if (c > 0xf4 || (c == 0xf4 && d > 0x8f))
      {
      *erroroffset = (int)(p - string) - 3;
      return PCRE_UTF8_ERR13;
      }
    break;

    /* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be
    rejected by the length test below. However, we do the appropriate tests
    here so that overlong sequences get diagnosed, and also in case there is
    ever an option for handling these larger code points. */

    /* 5-byte character. Check 3rd, 4th, and 5th bytes for 0x80. Then check for
    1111 1000, xx00 0xxx */

    case 4:
    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
      {
      *erroroffset = (int)(p - string) - 2;
      return PCRE_UTF8_ERR7;
      }
    if ((*(++p) & 0xc0) != 0x80)     /* Fourth byte */
      {
      *erroroffset = (int)(p - string) - 3;
      return PCRE_UTF8_ERR8;
      }
    if ((*(++p) & 0xc0) != 0x80)     /* Fifth byte */
      {
      *erroroffset = (int)(p - string) - 4;
      return PCRE_UTF8_ERR9;
      }
    if (c == 0xf8 && (d & 0x38) == 0)
      {
      *erroroffset = (int)(p - string) - 4;
      return PCRE_UTF8_ERR18;
      }
    break;

    /* 6-byte character. Check 3rd-6th bytes for 0x80. Then check for
    1111 1100, xx00 00xx. */

    case 5:
    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
      {
      *erroroffset = (int)(p - string) - 2;
      return PCRE_UTF8_ERR7;
      }
    if ((*(++p) & 0xc0) != 0x80)     /* Fourth byte */
      {
      *erroroffset = (int)(p - string) - 3;
      return PCRE_UTF8_ERR8;
      }
    if ((*(++p) & 0xc0) != 0x80)     /* Fifth byte */
      {
      *erroroffset = (int)(p - string) - 4;
      return PCRE_UTF8_ERR9;
      }
    if ((*(++p) & 0xc0) != 0x80)     /* Sixth byte */
      {
      *erroroffset = (int)(p - string) - 5;
      return PCRE_UTF8_ERR10;
      }
    if (c == 0xfc && (d & 0x3c) == 0)
      {
      *erroroffset = (int)(p - string) - 5;
      return PCRE_UTF8_ERR19;
      }
    break;
    }

  /* Character is valid under RFC 2279, but 4-byte and 5-byte characters are
  excluded by RFC 3629. The pointer p is currently at the last byte of the
  character. */

  if (ab > 3)
    {
    *erroroffset = (int)(p - string) - ab;
    return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12;
    }
  }

#else  /* SUPPORT_UTF */
(void)(string);  /* Keep picky compilers happy */
(void)(length);
#endif

return PCRE_UTF8_ERR0;   /* This indicates success */
}

/* End of VALIDUT8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_valid_utf8.c converted to VALIDUT8*/
/*autoconv-0010 VALIDUT8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 VALIDUT8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 VALIDUT8 line: 52 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 VALIDUT8 line: 302 pcre_valid_utf8 replaced by VALIDUT8*/
./ ADD NAME=ORD2UTF8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This file contains a private PCRE function that converts an ordinal
character value into a UTF8 string. */

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*       Convert character value to UTF-8         *
*************************************************/

/* This function takes an integer value in the range 0 - 0x10ffff
and encodes it as a UTF-8 character in 1 to 6 pcre_uchars.

Arguments:
  cvalue     the character value
  buffer     pointer to buffer for result - at least 6 pcre_uchars long

Returns:     number of characters placed in the buffer
*/

int
PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
{
#ifdef SUPPORT_UTF

register int i, j;

/* Checking invalid cvalue character, encoded as invalid UTF-16 character.
Should never happen in practice. */
if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000)
  cvalue = 0xfffe;

for (i = 0; i < PRIV(utf8_table1_size); i++)
  if ((int)cvalue <= PRIV(utf8_table1)[i]) break;
buffer += i;
for (j = i; j > 0; j--)
 {
 *buffer-- = 0x80 | (cvalue & 0x3f);
 cvalue >>= 6;
 }
*buffer = PRIV(utf8_table2)[i] | cvalue;
return i + 1;

#else

(void)(cvalue);  /* Keep compiler happy; this function won't ever be */
(void)(buffer);  /* called when SUPPORT_UTF is not defined. */
return 0;

#endif
}

/* End of ORD2UTF8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_ord2utf8.c converted to ORD2UTF8*/
/*autoconv-0010 ORD2UTF8 line: 45 added HAVE_CONFIG_H*/
/*autoconv-0011 ORD2UTF8 line: 48 config.h replaced by CONFIG.h*/
/*autoconv-0011 ORD2UTF8 line: 51 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 ORD2UTF8 line: 100 pcre_ord2utf8 replaced by ORD2UTF8*/
./ ADD NAME=PCREGREP 
/*************************************************
*               PCREGREP program                 *
*************************************************/

/* This is a grep program that uses the PCRE regular expression library to do
its pattern matching. On a Unix or Win32 system it can recurse into
directories.

           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <ctype.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef SUPPORT_LIBZ
#include <zlib.h>
#endif

#ifdef SUPPORT_LIBBZ2
#include <bzlib.h>
#endif

#include "PCRE.h"

#define FALSE 0
#define TRUE 1

typedef int BOOL;

#define MAX_PATTERN_COUNT 100
#define OFFSET_SIZE 99

#if BUFSIZ > 8192
#define PATBUFSIZE BUFSIZ
#else
#define PATBUFSIZE 8192
#endif

/* Values for the "filenames" variable, which specifies options for file name
output. The order is important; it is assumed that a file name is wanted for
all values greater than FN_DEFAULT. */

enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE };

/* File reading styles */

enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };

/* Actions for the -d and -D options */

enum { dee_READ, dee_SKIP, dee_RECURSE };
enum { DEE_READ, DEE_SKIP };

/* Actions for special processing options (flag bits) */

#define PO_WORD_MATCH     0x0001
#define PO_LINE_MATCH     0x0002
#define PO_FIXED_STRINGS  0x0004

/* Line ending types */

enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF };

/* Binary file options */

enum { BIN_BINARY, BIN_NOMATCH, BIN_TEXT };

/* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some
environments), a warning is issued if the value of fwrite() is ignored.
Unfortunately, casting to (void) does not suppress the warning. To get round
this, we use a macro that compiles a fudge. Oddly, this does not also seem to
apply to fprintf(). */

#define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}



/*************************************************
*               Global variables                 *
*************************************************/

/* Jeffrey Friedl has some debugging requirements that are not part of the
regular code. */

#ifdef JFRIEDL_DEBUG
static int S_arg = -1;
static unsigned int jfriedl_XR = 0; /* repeat regex attempt this many times */
static unsigned int jfriedl_XT = 0; /* replicate text this many times */
static const char *jfriedl_prefix = "";
static const char *jfriedl_postfix = "";
#endif

static int  endlinetype;

static char *colour_string = (char *)"1;31";
static char *colour_option = NULL;
static char *dee_option = NULL;
static char *DEE_option = NULL;
static char *main_buffer = NULL;
static char *newline = NULL;
static char *pattern_filename = NULL;
static char *stdin_name = (char *)"(standard input)";
static char *locale = NULL;

static const unsigned char *pcretables = NULL;

static int  pattern_count = 0;
static pcre **pattern_list = NULL;
static pcre_extra **hints_list = NULL;

static char *file_list = NULL;
static char *include_pattern = NULL;
static char *exclude_pattern = NULL;
static char *include_dir_pattern = NULL;
static char *exclude_dir_pattern = NULL;

static pcre *include_compiled = NULL;
static pcre *exclude_compiled = NULL;
static pcre *include_dir_compiled = NULL;
static pcre *exclude_dir_compiled = NULL;

static int after_context = 0;
static int before_context = 0;
static int binary_files = BIN_BINARY;
static int both_context = 0;
static int bufthird = PCREGREP_BUFSIZE;
static int bufsize = 3*PCREGREP_BUFSIZE;
static int dee_action = dee_READ;
static int DEE_action = DEE_READ;
static int error_count = 0;
static int filenames = FN_DEFAULT;
static int only_matching = -1;
static int process_options = 0;

#ifdef SUPPORT_PCREGREP_JIT
static int study_options = PCRE_STUDY_JIT_COMPILE;
#else
static int study_options = 0;
#endif

static unsigned long int match_limit = 0;
static unsigned long int match_limit_recursion = 0;

static BOOL count_only = FALSE;
static BOOL do_colour = FALSE;
static BOOL file_offsets = FALSE;
static BOOL hyphenpending = FALSE;
static BOOL invert = FALSE;
static BOOL line_buffered = FALSE;
static BOOL line_offsets = FALSE;
static BOOL multiline = FALSE;
static BOOL number = FALSE;
static BOOL omit_zero_count = FALSE;
static BOOL resource_error = FALSE;
static BOOL quiet = FALSE;
static BOOL silent = FALSE;
static BOOL utf8 = FALSE;

/* Structure for options and list of them */

enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER,
       OP_OP_NUMBER, OP_PATLIST, OP_BINFILES };

typedef struct option_item {
  int type;
  int one_char;
  void *dataptr;
  const char *long_name;
  const char *help_text;
} option_item;

/* Options without a single-letter equivalent get a negative value. This can be
used to identify them. */

#define N_COLOUR       (-1)
#define N_EXCLUDE      (-2)
#define N_EXCLUDE_DIR  (-3)
#define N_HELP         (-4)
#define N_INCLUDE      (-5)
#define N_INCLUDE_DIR  (-6)
#define N_LABEL        (-7)
#define N_LOCALE       (-8)
#define N_NULL         (-9)
#define N_LOFFSETS     (-10)
#define N_FOFFSETS     (-11)
#define N_LBUFFER      (-12)
#define N_M_LIMIT      (-13)
#define N_M_LIMIT_REC  (-14)
#define N_BUFSIZE      (-15)
#define N_NOJIT        (-16)
#define N_FILE_LIST    (-17)
#define N_BINARY_FILES (-18)

static option_item optionlist[] = {
  { OP_NODATA,     N_NULL,   NULL,              "",              "terminate options" },
  { OP_NODATA,     N_HELP,   NULL,              "help",          "display this help and exit" },
  { OP_NUMBER,     'A',      &after_context,    "after-context=number", "set number of following context lines" },
  { OP_NODATA,     'a',      NULL,              "text",          "treat binary files as text" },
  { OP_NUMBER,     'B',      &before_context,   "before-context=number", "set number of prior context lines" },
  { OP_BINFILES,   N_BINARY_FILES, NULL,        "binary-files=word", "set treatment of binary files" },
  { OP_NUMBER,     N_BUFSIZE,&bufthird,         "buffer-size=number", "set processing buffer size parameter" },
  { OP_OP_STRING,  N_COLOUR, &colour_option,    "color=option",  "matched text color option" },
  { OP_OP_STRING,  N_COLOUR, &colour_option,    "colour=option", "matched text colour option" },
  { OP_NUMBER,     'C',      &both_context,     "context=number", "set number of context lines, before & after" },
  { OP_NODATA,     'c',      NULL,              "count",         "print only a count of matching lines per FILE" },
  { OP_STRING,     'D',      &DEE_option,       "devices=action","how to handle devices, FIFOs, and sockets" },
  { OP_STRING,     'd',      &dee_option,       "directories=action", "how to handle directories" },
  { OP_PATLIST,    'e',      NULL,              "regex(p)=pattern", "specify pattern (may be used more than once)" },
  { OP_NODATA,     'F',      NULL,              "fixed-strings", "patterns are sets of newline-separated strings" },
  { OP_STRING,     'f',      &pattern_filename, "file=path",     "read patterns from file" },
  { OP_STRING,     N_FILE_LIST, &file_list,     "file-list=path","read files to search from file" },
  { OP_NODATA,     N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
  { OP_NODATA,     'H',      NULL,              "with-filename", "force the prefixing filename on output" },
  { OP_NODATA,     'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
  { OP_NODATA,     'I',      NULL,              "",              "treat binary files as not matching (ignore)" },
  { OP_NODATA,     'i',      NULL,              "ignore-case",   "ignore case distinctions" },
#ifdef SUPPORT_PCREGREP_JIT
  { OP_NODATA,     N_NOJIT,  NULL,              "no-jit",        "do not use just-in-time compiler optimization" },
#else
  { OP_NODATA,     N_NOJIT,  NULL,              "no-jit",        "ignored: this PCREGREP does not support JIT" },
#endif
  { OP_NODATA,     'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
  { OP_NODATA,     'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
  { OP_STRING,     N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
  { OP_NODATA,     N_LBUFFER, NULL,             "line-buffered", "use line buffering" },
  { OP_NODATA,     N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
  { OP_STRING,     N_LOCALE, &locale,           "locale=locale", "use the named locale" },
  { OP_LONGNUMBER, N_M_LIMIT, &match_limit,     "match-limit=number", "set PCRE match limit option" },
  { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" },
  { OP_NODATA,     'M',      NULL,              "multiline",     "run in multiline mode" },
  { OP_STRING,     'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
  { OP_NODATA,     'n',      NULL,              "line-number",   "print line number with output lines" },
  { OP_OP_NUMBER,  'o',      &only_matching,    "only-matching=n", "show only the part of the line that matched" },
  { OP_NODATA,     'q',      NULL,              "quiet",         "suppress output, just set return code" },
  { OP_NODATA,     'r',      NULL,              "recursive",     "recursively scan sub-directories" },
  { OP_STRING,     N_EXCLUDE,&exclude_pattern,  "exclude=pattern","exclude matching files when recursing" },
  { OP_STRING,     N_INCLUDE,&include_pattern,  "include=pattern","include matching files when recursing" },
  { OP_STRING,     N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude-dir=pattern","exclude matching directories when recursing" },
  { OP_STRING,     N_INCLUDE_DIR,&include_dir_pattern, "include-dir=pattern","include matching directories when recursing" },

  /* These two were accidentally implemented with underscores instead of
  hyphens in the option names. As this was not discovered for several releases,
  the incorrect versions are left in the table for compatibility. However, the
  --help function misses out any option that has an underscore in its name. */

  { OP_STRING,    N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
  { OP_STRING,    N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },

#ifdef JFRIEDL_DEBUG
  { OP_OP_NUMBER, 'S',      &S_arg,            "jeffS",         "replace matched (sub)string with X" },
#endif
  { OP_NODATA,    's',      NULL,              "no-messages",   "suppress error messages" },
  { OP_NODATA,    'u',      NULL,              "utf-8",         "use UTF-8 mode" },
  { OP_NODATA,    'V',      NULL,              "version",       "print version information and exit" },
  { OP_NODATA,    'v',      NULL,              "invert-match",  "select non-matching lines" },
  { OP_NODATA,    'w',      NULL,              "word-regex(p)", "force patterns to match only as words"  },
  { OP_NODATA,    'x',      NULL,              "line-regex(p)", "force patterns to match only whole lines" },
  { OP_NODATA,    0,        NULL,               NULL,            NULL }
};

/* Tables for prefixing and suffixing patterns, according to the -w, -x, and -F
options. These set the 1, 2, and 4 bits in process_options, respectively. Note
that the combination of -w and -x has the same effect as -x on its own, so we
can treat them as the same. */

static const char *prefix[] = {
  "", "\\b", "(?:", "(?:", "\\Q", "\\b\\Q", "(?:\\Q", "(?:\\Q" };

static const char *suffix[] = {
  "", "\\b", ")$",   ")$",   "\\E", "\\E\\b", "\\E)$",   "\\E)$" };

/* UTF-8 tables - used only when the newline setting is "any". */

const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};

const char utf8_table4[] = {
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };



/*************************************************
*         Exit from the program                  *
*************************************************/

/* If there has been a resource error, give a suitable message.

Argument:  the return code
Returns:   does not return
*/

static void
pcregrep_exit(int rc)
{
if (resource_error)
  {
  fprintf(stderr, "PCREGREP: Error %d, %d or %d means that a resource limit "
    "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT,
    PCRE_ERROR_JIT_STACKLIMIT);
  fprintf(stderr, "PCREGREP: Check your regex for nested unlimited loops.\n");
  }

exit(rc);
}


/*************************************************
*            OS-specific functions               *
*************************************************/

/* These functions are defined so that they can be made system specific,
although at present the only ones are for Unix, Win32, and for "no support". */


/************* Directory scanning in Unix ***********/

#if defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

typedef DIR directory_type;

static int
isdirectory(char *filename)
{
struct stat statbuf;
if (stat(filename, &statbuf) < 0)
  return 0;        /* In the expectation that opening as a file will fail */
return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0;
}

static directory_type *
opendirectory(char *filename)
{
return opendir(filename);
}

static char *
readdirectory(directory_type *dir)
{
for (;;)
  {
  struct dirent *dent = readdir(dir);
  if (dent == NULL) return NULL;
  if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
    return dent->d_name;
  }
/* Control never reaches here */
}

static void
closedirectory(directory_type *dir)
{
closedir(dir);
}


/************* Test for regular file in Unix **********/

static int
isregfile(char *filename)
{
struct stat statbuf;
if (stat(filename, &statbuf) < 0)
  return 1;        /* In the expectation that opening as a file will fail */
return (statbuf.st_mode & S_IFMT) == S_IFREG;
}


/************* Test for a terminal in Unix **********/

static BOOL
is_stdout_tty(void)
{
return isatty(fileno(stdout));
}

static BOOL
is_file_tty(FILE *f)
{
return isatty(fileno(f));
}


/************* Directory scanning in Win32 ***********/

/* I (Philip Hazel) have no means of testing this code. It was contributed by
Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
when it did not exist. David Byron added a patch that moved the #include of
<windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is
undefined when it is indeed undefined. */

#elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H

#ifndef STRICT
# define STRICT
#endif
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>

#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
#endif

typedef struct directory_type
{
HANDLE handle;
BOOL first;
WIN32_FIND_DATA data;
} directory_type;

int
isdirectory(char *filename)
{
DWORD attr = GetFileAttributes(filename);
if (attr == INVALID_FILE_ATTRIBUTES)
  return 0;
return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) ? '/' : 0;
}

directory_type *
opendirectory(char *filename)
{
size_t len;
char *pattern;
directory_type *dir;
DWORD err;
len = strlen(filename);
pattern = (char *) malloc(len + 3);
dir = (directory_type *) malloc(sizeof(*dir));
if ((pattern == NULL) || (dir == NULL))
  {
  fprintf(stderr, "PCREGREP: malloc failed\n");
  pcregrep_exit(2);
  }
memcpy(pattern, filename, len);
memcpy(&(pattern[len]), "\\*", 3);
dir->handle = FindFirstFile(pattern, &(dir->data));
if (dir->handle != INVALID_HANDLE_VALUE)
  {
  free(pattern);
  dir->first = TRUE;
  return dir;
  }
err = GetLastError();
free(pattern);
free(dir);
errno = (err == ERROR_ACCESS_DENIED) ? EACCES : ENOENT;
return NULL;
}

char *
readdirectory(directory_type *dir)
{
for (;;)
  {
  if (!dir->first)
    {
    if (!FindNextFile(dir->handle, &(dir->data)))
      return NULL;
    }
  else
    {
    dir->first = FALSE;
    }
  if (strcmp(dir->data.cFileName, ".") != 0 && strcmp(dir->data.cFileName, "..") != 0)
    return dir->data.cFileName;
  }
#ifndef _MSC_VER
return NULL;   /* Keep compiler happy; never executed */
#endif
}

void
closedirectory(directory_type *dir)
{
FindClose(dir->handle);
free(dir);
}


/************* Test for regular file in Win32 **********/

/* I don't know how to do this, or if it can be done; assume all paths are
regular if they are not directories. */

int isregfile(char *filename)
{
return !isdirectory(filename);
}


/************* Test for a terminal in Win32 **********/

/* I don't know how to do this; assume never */

static BOOL
is_stdout_tty(void)
{
return FALSE;
}

static BOOL
is_file_tty(FILE *f)
{
return FALSE;
}


/************* Directory scanning when we can't do it ***********/

/* The type is void, and apart from isdirectory(), the functions do nothing. */

#else

typedef void directory_type;

int isdirectory(char *filename) { return 0; }
directory_type * opendirectory(char *filename) { return (directory_type*)0;}
char *readdirectory(directory_type *dir) { return (char*)0;}
void closedirectory(directory_type *dir) {}


/************* Test for regular when we can't do it **********/

/* Assume all files are regular. */

int isregfile(char *filename) { return 1; }


/************* Test for a terminal when we can't do it **********/

static BOOL
is_stdout_tty(void)
{
return FALSE;
}

static BOOL
is_file_tty(FILE *f)
{
return FALSE;
}

#endif



#ifndef HAVE_STRERROR
/*************************************************
*     Provide strerror() for non-ANSI libraries  *
*************************************************/

/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()
in their libraries, but can provide the same facility by this simple
alternative function. */

extern int   sys_nerr;
extern char *sys_errlist[];

char *
strerror(int n)
{
if (n < 0 || n >= sys_nerr) return "unknown error number";
return sys_errlist[n];
}
#endif /* HAVE_STRERROR */



/*************************************************
*            Read one line of input              *
*************************************************/

/* Normally, input is read using fread() into a large buffer, so many lines may
be read at once. However, doing this for tty input means that no output appears
until a lot of input has been typed. Instead, tty input is handled line by
line. We cannot use fgets() for this, because it does not stop at a binary
zero, and therefore there is no way of telling how many characters it has read,
because there may be binary zeros embedded in the data.

Arguments:
  buffer     the buffer to read into
  length     the maximum number of characters to read
  f          the file

Returns:     the number of characters read, zero at end of file
*/

static unsigned int
read_one_line(char *buffer, int length, FILE *f)
{
int c;
int yield = 0;
while ((c = fgetc(f)) != EOF)
  {
  buffer[yield++] = c;
  if (c == '\n' || yield >= length) break;
  }
return yield;
}



/*************************************************
*             Find end of line                   *
*************************************************/

/* The length of the endline sequence that is found is set via lenptr. This may
be zero at the very end of the file if there is no line-ending sequence there.

Arguments:
  p         current position in line
  endptr    end of available data
  lenptr    where to put the length of the eol sequence

Returns:    pointer after the last byte of the line,
            including the newline byte(s)
*/

static char *
end_of_line(char *p, char *endptr, int *lenptr)
{
switch(endlinetype)
  {
  default:      /* Just in case */
  case EL_LF:
  while (p < endptr && *p != '\n') p++;
  if (p < endptr)
    {
    *lenptr = 1;
    return p + 1;
    }
  *lenptr = 0;
  return endptr;

  case EL_CR:
  while (p < endptr && *p != '\r') p++;
  if (p < endptr)
    {
    *lenptr = 1;
    return p + 1;
    }
  *lenptr = 0;
  return endptr;

  case EL_CRLF:
  for (;;)
    {
    while (p < endptr && *p != '\r') p++;
    if (++p >= endptr)
      {
      *lenptr = 0;
      return endptr;
      }
    if (*p == '\n')
      {
      *lenptr = 2;
      return p + 1;
      }
    }
  break;

  case EL_ANYCRLF:
  while (p < endptr)
    {
    int extra = 0;
    register int c = *((unsigned char *)p);

    if (utf8 && c >= 0xc0)
      {
      int gcii, gcss;
      extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
      gcss = 6*extra;
      c = (c & utf8_table3[extra]) << gcss;
      for (gcii = 1; gcii <= extra; gcii++)
        {
        gcss -= 6;
        c |= (p[gcii] & 0x3f) << gcss;
        }
      }

    p += 1 + extra;

    switch (c)
      {
      case 0x0a:    /* LF */
      *lenptr = 1;
      return p;

      case 0x0d:    /* CR */
      if (p < endptr && *p == 0x0a)
        {
        *lenptr = 2;
        p++;
        }
      else *lenptr = 1;
      return p;

      default:
      break;
      }
    }   /* End of loop for ANYCRLF case */

  *lenptr = 0;  /* Must have hit the end */
  return endptr;

  case EL_ANY:
  while (p < endptr)
    {
    int extra = 0;
    register int c = *((unsigned char *)p);

    if (utf8 && c >= 0xc0)
      {
      int gcii, gcss;
      extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
      gcss = 6*extra;
      c = (c & utf8_table3[extra]) << gcss;
      for (gcii = 1; gcii <= extra; gcii++)
        {
        gcss -= 6;
        c |= (p[gcii] & 0x3f) << gcss;
        }
      }

    p += 1 + extra;

    switch (c)
      {
      case 0x0a:    /* LF */
      case 0x0b:    /* VT */
      case 0x0c:    /* FF */
      *lenptr = 1;
      return p;

      case 0x0d:    /* CR */
      if (p < endptr && *p == 0x0a)
        {
        *lenptr = 2;
        p++;
        }
      else *lenptr = 1;
      return p;

      case 0x85:    /* NEL */
      *lenptr = utf8? 2 : 1;
      return p;

      case 0x2028:  /* LS */
      case 0x2029:  /* PS */
      *lenptr = 3;
      return p;

      default:
      break;
      }
    }   /* End of loop for ANY case */

  *lenptr = 0;  /* Must have hit the end */
  return endptr;
  }     /* End of overall switch */
}



/*************************************************
*         Find start of previous line            *
*************************************************/

/* This is called when looking back for before lines to print.

Arguments:
  p         start of the subsequent line
  startptr  start of available data

Returns:    pointer to the start of the previous line
*/

static char *
previous_line(char *p, char *startptr)
{
switch(endlinetype)
  {
  default:      /* Just in case */
  case EL_LF:
  p--;
  while (p > startptr && p[-1] != '\n') p--;
  return p;

  case EL_CR:
  p--;
  while (p > startptr && p[-1] != '\n') p--;
  return p;

  case EL_CRLF:
  for (;;)
    {
    p -= 2;
    while (p > startptr && p[-1] != '\n') p--;
    if (p <= startptr + 1 || p[-2] == '\r') return p;
    }
  return p;   /* But control should never get here */

  case EL_ANY:
  case EL_ANYCRLF:
  if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;
  if (utf8) while ((*p & 0xc0) == 0x80) p--;

  while (p > startptr)
    {
    register int c;
    char *pp = p - 1;

    if (utf8)
      {
      int extra = 0;
      while ((*pp & 0xc0) == 0x80) pp--;
      c = *((unsigned char *)pp);
      if (c >= 0xc0)
        {
        int gcii, gcss;
        extra = utf8_table4[c & 0x3f];  /* Number of additional bytes */
        gcss = 6*extra;
        c = (c & utf8_table3[extra]) << gcss;
        for (gcii = 1; gcii <= extra; gcii++)
          {
          gcss -= 6;
          c |= (pp[gcii] & 0x3f) << gcss;
          }
        }
      }
    else c = *((unsigned char *)pp);

    if (endlinetype == EL_ANYCRLF) switch (c)
      {
      case 0x0a:    /* LF */
      case 0x0d:    /* CR */
      return p;

      default:
      break;
      }

    else switch (c)
      {
      case 0x0a:    /* LF */
      case 0x0b:    /* VT */
      case 0x0c:    /* FF */
      case 0x0d:    /* CR */
      case 0x85:    /* NEL */
      case 0x2028:  /* LS */
      case 0x2029:  /* PS */
      return p;

      default:
      break;
      }

    p = pp;  /* Back one character */
    }        /* End of loop for ANY case */

  return startptr;  /* Hit start of data */
  }     /* End of overall switch */
}





/*************************************************
*       Print the previous "after" lines         *
*************************************************/

/* This is called if we are about to lose said lines because of buffer filling,
and at the end of the file. The data in the line is written using fwrite() so
that a binary zero does not terminate it.

Arguments:
  lastmatchnumber   the number of the last matching line, plus one
  lastmatchrestart  where we restarted after the last match
  endptr            end of available data
  printname         filename for printing

Returns:            nothing
*/

static void do_after_lines(int lastmatchnumber, char *lastmatchrestart,
  char *endptr, char *printname)
{
if (after_context > 0 && lastmatchnumber > 0)
  {
  int count = 0;
  while (lastmatchrestart < endptr && count++ < after_context)
    {
    int ellength;
    char *pp = lastmatchrestart;
    if (printname != NULL) fprintf(stdout, "%s-", printname);
    if (number) fprintf(stdout, "%d-", lastmatchnumber++);
    pp = end_of_line(pp, endptr, &ellength);
    FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
    lastmatchrestart = pp;
    }
  hyphenpending = TRUE;
  }
}



/*************************************************
*   Apply patterns to subject till one matches   *
*************************************************/

/* This function is called to run through all patterns, looking for a match. It
is used multiple times for the same subject when colouring is enabled, in order
to find all possible matches.

Arguments:
  matchptr     the start of the subject
  length       the length of the subject to match
  startoffset  where to start matching
  offsets      the offets vector to fill in
  mrc          address of where to put the result of PCREXEC8()

Returns:      TRUE if there was a match
              FALSE if there was no match
              invert if there was a non-fatal error
*/

static BOOL
match_patterns(char *matchptr, size_t length, int startoffset, int *offsets,
  int *mrc)
{
int i;
size_t slen = length;
const char *msg = "this text:\n\n";
if (slen > 200)
  {
  slen = 200;
  msg = "text that starts:\n\n";
  }
for (i = 0; i < pattern_count; i++)
  {
  *mrc = PCREXEC8(pattern_list[i], hints_list[i], matchptr, (int)length,
    startoffset, PCRE_NOTEMPTY, offsets, OFFSET_SIZE);
  if (*mrc >= 0) return TRUE;
  if (*mrc == PCRE_ERROR_NOMATCH) continue;
  fprintf(stderr, "PCREGREP: PCREXEC8() gave error %d while matching ", *mrc);
  if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
  fprintf(stderr, "%s", msg);
  FWRITE(matchptr, 1, slen, stderr);   /* In case binary zero included */
  fprintf(stderr, "\n\n");
  if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT ||
      *mrc == PCRE_ERROR_JIT_STACKLIMIT)
    resource_error = TRUE;
  if (error_count++ > 20)
    {
    fprintf(stderr, "PCREGREP: Too many errors - abandoned.\n");
    pcregrep_exit(2);
    }
  return invert;    /* No more matching; don't show the line again */
  }

return FALSE;  /* No match, no errors */
}



/*************************************************
*            Grep an individual file             *
*************************************************/

/* This is called from grep_or_recurse() below. It uses a buffer that is three
times the value of bufthird. The matching point is never allowed to stray into
the top third of the buffer, thus keeping more of the file available for
context printing or for multiline scanning. For large files, the pointer will
be in the middle third most of the time, so the bottom third is available for
"before" context printing.

Arguments:
  handle       the fopened FILE stream for a normal file
               the gzFile pointer when reading is via libz
               the BZFILE pointer when reading is via libbz2
  frtype       FR_PLAIN, FR_LIBZ, or FR_LIBBZ2
  filename     the file name or NULL (for errors)
  printname    the file name if it is to be printed for each match
               or NULL if the file name is not to be printed
               it cannot be NULL if filenames[_nomatch]_only is set

Returns:       0 if there was at least one match
               1 otherwise (no matches)
               2 if an overlong line is encountered
               3 if there is a read error on a .bz2 file
*/

static int
PCREGREP(void *handle, int frtype, char *filename, char *printname)
{
int rc = 1;
int linenumber = 1;
int lastmatchnumber = 0;
int count = 0;
int filepos = 0;
int offsets[OFFSET_SIZE];
char *lastmatchrestart = NULL;
char *ptr = main_buffer;
char *endptr;
size_t bufflength;
BOOL binary = FALSE;
BOOL endhyphenpending = FALSE;
BOOL input_line_buffered = line_buffered;
FILE *in = NULL;                    /* Ensure initialized */

#ifdef SUPPORT_LIBZ
gzFile ingz = NULL;
#endif

#ifdef SUPPORT_LIBBZ2
BZFILE *inbz2 = NULL;
#endif


/* Do the first read into the start of the buffer and set up the pointer to end
of what we have. In the case of libz, a non-zipped .gz file will be read as a
plain file. However, if a .bz2 file isn't actually bzipped, the first read will
fail. */

#ifdef SUPPORT_LIBZ
if (frtype == FR_LIBZ)
  {
  ingz = (gzFile)handle;
  bufflength = gzread (ingz, main_buffer, bufsize);
  }
else
#endif

#ifdef SUPPORT_LIBBZ2
if (frtype == FR_LIBBZ2)
  {
  inbz2 = (BZFILE *)handle;
  bufflength = BZ2_bzread(inbz2, main_buffer, bufsize);
  if ((int)bufflength < 0) return 2;   /* Gotcha: bufflength is size_t; */
  }                                    /* without the cast it is unsigned. */
else
#endif

  {
  in = (FILE *)handle;
  if (is_file_tty(in)) input_line_buffered = TRUE;
  bufflength = input_line_buffered?
    read_one_line(main_buffer, bufsize, in) :
    fread(main_buffer, 1, bufsize, in);
  }

endptr = main_buffer + bufflength;

/* Unless binary-files=text, see if we have a binary file. This uses the same
rule as GNU grep, namely, a search for a binary zero byte near the start of the
file. */

if (binary_files != BIN_TEXT)
  {
  binary =
    memchr(main_buffer, 0, (bufflength > 1024)? 1024 : bufflength) != NULL;
  if (binary && binary_files == BIN_NOMATCH) return 1;
  }

/* Loop while the current pointer is not at the end of the file. For large
files, endptr will be at the end of the buffer when we are in the middle of the
file, but ptr will never get there, because as soon as it gets over 2/3 of the
way, the buffer is shifted left and re-filled. */

while (ptr < endptr)
  {
  int endlinelength;
  int mrc = 0;
  int startoffset = 0;
  BOOL match;
  char *matchptr = ptr;
  char *t = ptr;
  size_t length, linelength;

  /* At this point, ptr is at the start of a line. We need to find the length
  of the subject string to pass to PCREXEC8(). In multiline mode, it is the
  length remainder of the data in the buffer. Otherwise, it is the length of
  the next line, excluding the terminating newline. After matching, we always
  advance by the length of the next line. In multiline mode the PCRE_FIRSTLINE
  option is used for compiling, so that any match is constrained to be in the
  first line. */

  t = end_of_line(t, endptr, &endlinelength);
  linelength = t - ptr - endlinelength;
  length = multiline? (size_t)(endptr - ptr) : linelength;

  /* Check to see if the line we are looking at extends right to the very end
  of the buffer without a line terminator. This means the line is too long to
  handle. */

  if (endlinelength == 0 && t == main_buffer + bufsize)
    {
    fprintf(stderr, "PCREGREP: line %d%s%s is too long for the internal buffer\n"
                    "PCREGREP: check the --buffer-size option\n",
                    linenumber,
                    (filename == NULL)? "" : " of file ",
                    (filename == NULL)? "" : filename);
    return 2;
    }

  /* Extra processing for Jeffrey Friedl's debugging. */

#ifdef JFRIEDL_DEBUG
  if (jfriedl_XT || jfriedl_XR)
  {
      #include <sys/time.h>
      #include <time.h>
      struct timeval start_time, end_time;
      struct timezone dummy;
      int i;

      if (jfriedl_XT)
      {
          unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix);
          const char *orig = ptr;
          ptr = malloc(newlen + 1);
          if (!ptr) {
                  printf("out of memory");
                  pcregrep_exit(2);
          }
          endptr = ptr;
          strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);
          for (i = 0; i < jfriedl_XT; i++) {
                  strncpy(endptr, orig,  length);
                  endptr += length;
          }
          strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix);
          length = newlen;
      }

      if (gettimeofday(&start_time, &dummy) != 0)
              perror("bad gettimeofday");


      for (i = 0; i < jfriedl_XR; i++)
          match = (PCREXEC8(pattern_list[0], hints_list[0], ptr, length, 0,
              PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);

      if (gettimeofday(&end_time, &dummy) != 0)
              perror("bad gettimeofday");

      double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0))
                      -
                      (start_time.tv_sec + (start_time.tv_usec / 1000000.0)));

      printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta);
      return 0;
  }
#endif

  /* We come back here after a match when the -o option (only_matching) is set,
  in order to find any further matches in the same line. */

  ONLY_MATCHING_RESTART:

  /* Run through all the patterns until one matches or there is an error other
  than NOMATCH. This code is in a subroutine so that it can be re-used for
  finding subsequent matches when colouring matched lines. */

  match = match_patterns(matchptr, length, startoffset, offsets, &mrc);

  /* If it's a match or a not-match (as required), do what's wanted. */

  if (match != invert)
    {
    BOOL hyphenprinted = FALSE;

    /* We've failed if we want a file that doesn't have any matches. */

    if (filenames == FN_NOMATCH_ONLY) return 1;

    /* Just count if just counting is wanted. */

    if (count_only) count++;

    /* When handling a binary file and binary-files==binary, the "binary"
    variable will be set true (it's false in all other cases). In this
    situation we just want to output the file name. No need to scan further. */

    else if (binary)
      {
      fprintf(stdout, "Binary file %s matches\n", filename);
      return 0;
      }

    /* If all we want is a file name, there is no need to scan any more lines
    in the file. */

    else if (filenames == FN_MATCH_ONLY)
      {
      fprintf(stdout, "%s\n", printname);
      return 0;
      }

    /* Likewise, if all we want is a yes/no answer. */

    else if (quiet) return 0;

    /* The --only-matching option prints just the substring that matched, or a
    captured portion of it, as long as this string is not empty, and the
    --file-offsets and --line-offsets options output offsets for the matching
    substring (they both force --only-matching = 0). None of these options
    prints any context. Afterwards, adjust the start and then jump back to look
    for further matches in the same line. If we are in invert mode, however,
    nothing is printed and we do not restart - this could still be useful
    because the return code is set. */

    else if (only_matching >= 0)
      {
      if (!invert)
        {
        if (printname != NULL) fprintf(stdout, "%s:", printname);
        if (number) fprintf(stdout, "%d:", linenumber);
        if (line_offsets)
          fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
            offsets[1] - offsets[0]);
        else if (file_offsets)
          fprintf(stdout, "%d,%d\n",
            (int)(filepos + matchptr + offsets[0] - ptr),
            offsets[1] - offsets[0]);
        else if (only_matching < mrc)
          {
          int plen = offsets[2*only_matching + 1] - offsets[2*only_matching];
          if (plen > 0)
            {
            if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
            FWRITE(matchptr + offsets[only_matching*2], 1, plen, stdout);
            if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
            fprintf(stdout, "\n");
            }
          }
        else if (printname != NULL || number) fprintf(stdout, "\n");
        match = FALSE;
        if (line_buffered) fflush(stdout);
        rc = 0;                      /* Had some success */
        startoffset = offsets[1];    /* Restart after the match */
        goto ONLY_MATCHING_RESTART;
        }
      }

    /* This is the default case when none of the above options is set. We print
    the matching lines(s), possibly preceded and/or followed by other lines of
    context. */

    else
      {
      /* See if there is a requirement to print some "after" lines from a
      previous match. We never print any overlaps. */

      if (after_context > 0 && lastmatchnumber > 0)
        {
        int ellength;
        int linecount = 0;
        char *p = lastmatchrestart;

        while (p < ptr && linecount < after_context)
          {
          p = end_of_line(p, ptr, &ellength);
          linecount++;
          }

        /* It is important to advance lastmatchrestart during this printing so
        that it interacts correctly with any "before" printing below. Print
        each line's data using fwrite() in case there are binary zeroes. */

        while (lastmatchrestart < p)
          {
          char *pp = lastmatchrestart;
          if (printname != NULL) fprintf(stdout, "%s-", printname);
          if (number) fprintf(stdout, "%d-", lastmatchnumber++);
          pp = end_of_line(pp, endptr, &ellength);
          FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
          lastmatchrestart = pp;
          }
        if (lastmatchrestart != ptr) hyphenpending = TRUE;
        }

      /* If there were non-contiguous lines printed above, insert hyphens. */

      if (hyphenpending)
        {
        fprintf(stdout, "--\n");
        hyphenpending = FALSE;
        hyphenprinted = TRUE;
        }

      /* See if there is a requirement to print some "before" lines for this
      match. Again, don't print overlaps. */

      if (before_context > 0)
        {
        int linecount = 0;
        char *p = ptr;

        while (p > main_buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
               linecount < before_context)
          {
          linecount++;
          p = previous_line(p, main_buffer);
          }

        if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
          fprintf(stdout, "--\n");

        while (p < ptr)
          {
          int ellength;
          char *pp = p;
          if (printname != NULL) fprintf(stdout, "%s-", printname);
          if (number) fprintf(stdout, "%d-", linenumber - linecount--);
          pp = end_of_line(pp, endptr, &ellength);
          FWRITE(p, 1, pp - p, stdout);
          p = pp;
          }
        }

      /* Now print the matching line(s); ensure we set hyphenpending at the end
      of the file if any context lines are being output. */

      if (after_context > 0 || before_context > 0)
        endhyphenpending = TRUE;

      if (printname != NULL) fprintf(stdout, "%s:", printname);
      if (number) fprintf(stdout, "%d:", linenumber);

      /* In multiline mode, we want to print to the end of the line in which
      the end of the matched string is found, so we adjust linelength and the
      line number appropriately, but only when there actually was a match
      (invert not set). Because the PCRE_FIRSTLINE option is set, the start of
      the match will always be before the first newline sequence. */

      if (multiline & !invert)
        {
        char *endmatch = ptr + offsets[1];
        t = ptr;
        while (t < endmatch)
          {
          t = end_of_line(t, endptr, &endlinelength);
          if (t < endmatch) linenumber++; else break;
          }
        linelength = t - ptr - endlinelength;
        }

      /*** NOTE: Use only fwrite() to output the data line, so that binary
      zeroes are treated as just another data character. */

      /* This extra option, for Jeffrey Friedl's debugging requirements,
      replaces the matched string, or a specific captured string if it exists,
      with X. When this happens, colouring is ignored. */

#ifdef JFRIEDL_DEBUG
      if (S_arg >= 0 && S_arg < mrc)
        {
        int first = S_arg * 2;
        int last  = first + 1;
        FWRITE(ptr, 1, offsets[first], stdout);
        fprintf(stdout, "X");
        FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout);
        }
      else
#endif

      /* We have to split the line(s) up if colouring, and search for further
      matches, but not of course if the line is a non-match. */

      if (do_colour && !invert)
        {
        int plength;
        FWRITE(ptr, 1, offsets[0], stdout);
        fprintf(stdout, "%c[%sm", 0x1b, colour_string);
        FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
        fprintf(stdout, "%c[00m", 0x1b);
        for (;;)
          {
          startoffset = offsets[1];
          if (startoffset >= (int)linelength + endlinelength ||
              !match_patterns(matchptr, length, startoffset, offsets, &mrc))
            break;
          FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
          FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
          fprintf(stdout, "%c[00m", 0x1b);
          }

        /* In multiline mode, we may have already printed the complete line
        and its line-ending characters (if they matched the pattern), so there
        may be no more to print. */

        plength = (int)((linelength + endlinelength) - startoffset);
        if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout);
        }

      /* Not colouring; no need to search for further matches */

      else FWRITE(ptr, 1, linelength + endlinelength, stdout);
      }

    /* End of doing what has to be done for a match. If --line-buffered was
    given, flush the output. */

    if (line_buffered) fflush(stdout);
    rc = 0;    /* Had some success */

    /* Remember where the last match happened for after_context. We remember
    where we are about to restart, and that line's number. */

    lastmatchrestart = ptr + linelength + endlinelength;
    lastmatchnumber = linenumber + 1;
    }

  /* For a match in multiline inverted mode (which of course did not cause
  anything to be printed), we have to move on to the end of the match before
  proceeding. */

  if (multiline && invert && match)
    {
    int ellength;
    char *endmatch = ptr + offsets[1];
    t = ptr;
    while (t < endmatch)
      {
      t = end_of_line(t, endptr, &ellength);
      if (t <= endmatch) linenumber++; else break;
      }
    endmatch = end_of_line(endmatch, endptr, &ellength);
    linelength = endmatch - ptr - ellength;
    }

  /* Advance to after the newline and increment the line number. The file
  offset to the current line is maintained in filepos. */

  ptr += linelength + endlinelength;
  filepos += (int)(linelength + endlinelength);
  linenumber++;

  /* If input is line buffered, and the buffer is not yet full, read another
  line and add it into the buffer. */

  if (input_line_buffered && bufflength < (size_t)bufsize)
    {
    int add = read_one_line(ptr, bufsize - (int)(ptr - main_buffer), in);
    bufflength += add;
    endptr += add;
    }

  /* If we haven't yet reached the end of the file (the buffer is full), and
  the current point is in the top 1/3 of the buffer, slide the buffer down by
  1/3 and refill it. Before we do this, if some unprinted "after" lines are
  about to be lost, print them. */

  if (bufflength >= (size_t)bufsize && ptr > main_buffer + 2*bufthird)
    {
    if (after_context > 0 &&
        lastmatchnumber > 0 &&
        lastmatchrestart < main_buffer + bufthird)
      {
      do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
      lastmatchnumber = 0;
      }

    /* Now do the shuffle */

    memmove(main_buffer, main_buffer + bufthird, 2*bufthird);
    ptr -= bufthird;

#ifdef SUPPORT_LIBZ
    if (frtype == FR_LIBZ)
      bufflength = 2*bufthird +
        gzread (ingz, main_buffer + 2*bufthird, bufthird);
    else
#endif

#ifdef SUPPORT_LIBBZ2
    if (frtype == FR_LIBBZ2)
      bufflength = 2*bufthird +
        BZ2_bzread(inbz2, main_buffer + 2*bufthird, bufthird);
    else
#endif

    bufflength = 2*bufthird +
      (input_line_buffered?
       read_one_line(main_buffer + 2*bufthird, bufthird, in) :
       fread(main_buffer + 2*bufthird, 1, bufthird, in));
    endptr = main_buffer + bufflength;

    /* Adjust any last match point */

    if (lastmatchnumber > 0) lastmatchrestart -= bufthird;
    }
  }     /* Loop through the whole file */

/* End of file; print final "after" lines if wanted; do_after_lines sets
hyphenpending if it prints something. */

if (only_matching < 0 && !count_only)
  {
  do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
  hyphenpending |= endhyphenpending;
  }

/* Print the file name if we are looking for those without matches and there
were none. If we found a match, we won't have got this far. */

if (filenames == FN_NOMATCH_ONLY)
  {
  fprintf(stdout, "%s\n", printname);
  return 0;
  }

/* Print the match count if wanted */

if (count_only)
  {
  if (count > 0 || !omit_zero_count)
    {
    if (printname != NULL && filenames != FN_NONE)
      fprintf(stdout, "%s:", printname);
    fprintf(stdout, "%d\n", count);
    }
  }

return rc;
}



/*************************************************
*     Grep a file or recurse into a directory    *
*************************************************/

/* Given a path name, if it's a directory, scan all the files if we are
recursing; if it's a file, grep it.

Arguments:
  pathname          the path to investigate
  dir_recurse       TRUE if recursing is wanted (-r or -drecurse)
  only_one_at_top   TRUE if the path is the only one at toplevel

Returns:   0 if there was at least one match
           1 if there were no matches
           2 there was some kind of error

However, file opening failures are suppressed if "silent" is set.
*/

static int
grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top)
{
int rc = 1;
int sep;
int frtype;
void *handle;
FILE *in = NULL;           /* Ensure initialized */

#ifdef SUPPORT_LIBZ
gzFile ingz = NULL;
#endif

#ifdef SUPPORT_LIBBZ2
BZFILE *inbz2 = NULL;
#endif

#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
int pathlen;
#endif

/* If the file name is "-" we scan stdin */

if (strcmp(pathname, "-") == 0)
  {
  return PCREGREP(stdin, FR_PLAIN, stdin_name,
    (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?
      stdin_name : NULL);
  }

/* If the file is a directory, skip if skipping or if we are recursing, scan
each file and directory within it, subject to any include or exclude patterns
that were set. The scanning code is localized so it can be made
system-specific. */

if ((sep = isdirectory(pathname)) != 0)
  {
  if (dee_action == dee_SKIP) return 1;
  if (dee_action == dee_RECURSE)
    {
    char buffer[1024];
    char *nextfile;
    directory_type *dir = opendirectory(pathname);

    if (dir == NULL)
      {
      if (!silent)
        fprintf(stderr, "PCREGREP: Failed to open directory %s: %s\n", pathname,
          strerror(errno));
      return 2;
      }

    while ((nextfile = readdirectory(dir)) != NULL)
      {
      int frc, nflen;
      sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
      nflen = (int)(strlen(nextfile));

      if (isdirectory(buffer))
        {
        if (exclude_dir_compiled != NULL &&
            PCREXEC8(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
          continue;

        if (include_dir_compiled != NULL &&
            PCREXEC8(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
          continue;
        }
      else
        {
        if (exclude_compiled != NULL &&
            PCREXEC8(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
          continue;

        if (include_compiled != NULL &&
            PCREXEC8(include_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
          continue;
        }

      frc = grep_or_recurse(buffer, dir_recurse, FALSE);
      if (frc > 1) rc = frc;
       else if (frc == 0 && rc == 1) rc = 0;
      }

    closedirectory(dir);
    return rc;
    }
  }

/* If the file is not a directory and not a regular file, skip it if that's
been requested. */

else if (!isregfile(pathname) && DEE_action == DEE_SKIP) return 1;

/* Control reaches here if we have a regular file, or if we have a directory
and recursion or skipping was not requested, or if we have anything else and
skipping was not requested. The scan proceeds. If this is the first and only
argument at top level, we don't show the file name, unless we are only showing
the file name, or the filename was forced (-H). */

#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
pathlen = (int)(strlen(pathname));
#endif

/* Open using zlib if it is supported and the file name ends with .gz. */

#ifdef SUPPORT_LIBZ
if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)
  {
  ingz = gzopen(pathname, "rb");
  if (ingz == NULL)
    {
    if (!silent)
      fprintf(stderr, "PCREGREP: Failed to open %s: %s\n", pathname,
        strerror(errno));
    return 2;
    }
  handle = (void *)ingz;
  frtype = FR_LIBZ;
  }
else
#endif

/* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */

#ifdef SUPPORT_LIBBZ2
if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)
  {
  inbz2 = BZ2_bzopen(pathname, "rb");
  handle = (void *)inbz2;
  frtype = FR_LIBBZ2;
  }
else
#endif

/* Otherwise use plain fopen(). The label is so that we can come back here if
an attempt to read a .bz2 file indicates that it really is a plain file. */

#ifdef SUPPORT_LIBBZ2
PLAIN_FILE:
#endif
  {
  in = fopen(pathname, "r");
  handle = (void *)in;
  frtype = FR_PLAIN;
  }

/* All the opening methods return errno when they fail. */

if (handle == NULL)
  {
  if (!silent)
    fprintf(stderr, "PCREGREP: Failed to open %s: %s\n", pathname,
      strerror(errno));
  return 2;
  }

/* Now grep the file */

rc = PCREGREP(handle, frtype, pathname, (filenames > FN_DEFAULT ||
  (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);

/* Close in an appropriate manner. */

#ifdef SUPPORT_LIBZ
if (frtype == FR_LIBZ)
  gzclose(ingz);
else
#endif

/* If it is a .bz2 file and the result is 3, it means that the first attempt to
read failed. If the error indicates that the file isn't in fact bzipped, try
again as a normal file. */

#ifdef SUPPORT_LIBBZ2
if (frtype == FR_LIBBZ2)
  {
  if (rc == 3)
    {
    int errnum;
    const char *err = BZ2_bzerror(inbz2, &errnum);
    if (errnum == BZ_DATA_ERROR_MAGIC)
      {
      BZ2_bzclose(inbz2);
      goto PLAIN_FILE;
      }
    else if (!silent)
      fprintf(stderr, "PCREGREP: Failed to read %s using bzlib: %s\n",
        pathname, err);
    rc = 2;    /* The normal "something went wrong" code */
    }
  BZ2_bzclose(inbz2);
  }
else
#endif

/* Normal file close */

fclose(in);

/* Pass back the yield from PCREGREP(). */

return rc;
}




/*************************************************
*                Usage function                  *
*************************************************/

static int
usage(int rc)
{
option_item *op;
fprintf(stderr, "Usage: PCREGREP [-");
for (op = optionlist; op->one_char != 0; op++)
  {
  if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
  }
fprintf(stderr, "] [long options] [pattern] [files]\n");
fprintf(stderr, "Type `PCREGREP --help' for more information and the long "
  "options.\n");
return rc;
}




/*************************************************
*                Help function                   *
*************************************************/

static void
help(void)
{
option_item *op;

printf("Usage: PCREGREP [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
printf("Search for PATTERN in each FILE or standard input.\n");
printf("PATTERN must be present if neither -e nor -f is used.\n");
printf("\"-\" can be used as a file name to mean STDIN.\n");

#ifdef SUPPORT_LIBZ
printf("Files whose names end in .gz are read using zlib.\n");
#endif

#ifdef SUPPORT_LIBBZ2
printf("Files whose names end in .bz2 are read using bzlib2.\n");
#endif

#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
printf("Other files and the standard input are read as plain files.\n\n");
#else
printf("All files are read as plain files, without any interpretation.\n\n");
#endif

printf("Example: PCREGREP -i 'hello.*world' menu.h main.c\n\n");
printf("Options:\n");

for (op = optionlist; op->one_char != 0; op++)
  {
  int n;
  char s[4];

  /* Two options were accidentally implemented and documented with underscores
  instead of hyphens in their names, something that was not noticed for quite a
  few releases. When fixing this, I left the underscored versions in the list
  in case people were using them. However, we don't want to display them in the
  help data. There are no other options that contain underscores, and we do not
  expect ever to implement such options. Therefore, just omit any option that
  contains an underscore. */

  if (strchr(op->long_name, '_') != NULL) continue;

  if (op->one_char > 0 && (op->long_name)[0] == 0)
    n = 31 - printf("  -%c", op->one_char);
  else
    {
    if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);
      else strcpy(s, "   ");
    n = 31 - printf("  %s --%s", s, op->long_name);
    }

  if (n < 1) n = 1;
  printf("%.*s%s\n", n, "                           ", op->help_text);
  }

printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n");
printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE);
printf("When reading patterns or file names from a file, trailing white\n");
printf("space is removed and blank lines are ignored.\n");
printf("There is a maximum of %d patterns, each of maximum size %d bytes.\n",
  MAX_PATTERN_COUNT, PATBUFSIZE);

printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");
printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");
}




/*************************************************
*    Handle a single-letter, no data option      *
*************************************************/

static int
handle_option(int letter, int options)
{
switch(letter)
  {
  case N_FOFFSETS: file_offsets = TRUE; break;
  case N_HELP: help(); pcregrep_exit(0);
  case N_LBUFFER: line_buffered = TRUE; break;
  case N_LOFFSETS: line_offsets = number = TRUE; break;
  case N_NOJIT: study_options &= ~PCRE_STUDY_JIT_COMPILE; break;
  case 'a': binary_files = BIN_TEXT; break;
  case 'c': count_only = TRUE; break;
  case 'F': process_options |= PO_FIXED_STRINGS; break;
  case 'H': filenames = FN_FORCE; break;
  case 'I': binary_files = BIN_NOMATCH; break;
  case 'h': filenames = FN_NONE; break;
  case 'i': options |= PCRE_CASELESS; break;
  case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;
  case 'L': filenames = FN_NOMATCH_ONLY; break;
  case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break;
  case 'n': number = TRUE; break;
  case 'o': only_matching = 0; break;
  case 'q': quiet = TRUE; break;
  case 'r': dee_action = dee_RECURSE; break;
  case 's': silent = TRUE; break;
  case 'u': options |= PCRE_UTF8; utf8 = TRUE; break;
  case 'v': invert = TRUE; break;
  case 'w': process_options |= PO_WORD_MATCH; break;
  case 'x': process_options |= PO_LINE_MATCH; break;

  case 'V':
  fprintf(stderr, "PCREGREP version %s\n", VERSION8());
  pcregrep_exit(0);
  break;

  default:
  fprintf(stderr, "PCREGREP: Unknown option -%c\n", letter);
  pcregrep_exit(usage(2));
  }

return options;
}




/*************************************************
*          Construct printed ordinal             *
*************************************************/

/* This turns a number into "1st", "3rd", etc. */

static char *
ordin(int n)
{
static char buffer[8];
char *p = buffer;
sprintf(p, "%d", n);
while (*p != 0) p++;
switch (n%10)
  {
  case 1: strcpy(p, "st"); break;
  case 2: strcpy(p, "nd"); break;
  case 3: strcpy(p, "rd"); break;
  default: strcpy(p, "th"); break;
  }
return buffer;
}



/*************************************************
*          Compile a single pattern              *
*************************************************/

/* When the -F option has been used, this is called for each substring.
Otherwise it's called for each supplied pattern.

Arguments:
  pattern        the pattern string
  options        the PCRE options
  filename       the file name, or NULL for a command-line pattern
  count          0 if this is the only command line pattern, or
                 number of the command line pattern, or
                 linenumber for a pattern from a file

Returns:         TRUE on success, FALSE after an error
*/

static BOOL
compile_single_pattern(char *pattern, int options, char *filename, int count)
{
char buffer[PATBUFSIZE];
const char *error;
int errptr;

if (pattern_count >= MAX_PATTERN_COUNT)
  {
  fprintf(stderr, "PCREGREP: Too many %spatterns (max %d)\n",
    (filename == NULL)? "command-line " : "", MAX_PATTERN_COUNT);
  return FALSE;
  }

sprintf(buffer, "%s%.*s%s", prefix[process_options], bufthird, pattern,
  suffix[process_options]);
pattern_list[pattern_count] =
  COMPILE8(buffer, options, &error, &errptr, pcretables);
if (pattern_list[pattern_count] != NULL)
  {
  pattern_count++;
  return TRUE;
  }

/* Handle compile errors */

errptr -= (int)strlen(prefix[process_options]);
if (errptr > (int)strlen(pattern)) errptr = (int)strlen(pattern);

if (filename == NULL)
  {
  if (count == 0)
    fprintf(stderr, "PCREGREP: Error in command-line regex "
      "at offset %d: %s\n", errptr, error);
  else
    fprintf(stderr, "PCREGREP: Error in %s command-line regex "
      "at offset %d: %s\n", ordin(count), errptr, error);
  }
else
  {
  fprintf(stderr, "PCREGREP: Error in regex in line %d of %s "
    "at offset %d: %s\n", count, filename, errptr, error);
  }

return FALSE;
}



/*************************************************
*           Compile one supplied pattern         *
*************************************************/

/* When the -F option has been used, each string may be a list of strings,
separated by line breaks. They will be matched literally.

Arguments:
  pattern        the pattern string
  options        the PCRE options
  filename       the file name, or NULL for a command-line pattern
  count          0 if this is the only command line pattern, or
                 number of the command line pattern, or
                 linenumber for a pattern from a file

Returns:         TRUE on success, FALSE after an error
*/

static BOOL
compile_pattern(char *pattern, int options, char *filename, int count)
{
if ((process_options & PO_FIXED_STRINGS) != 0)
  {
  char *eop = pattern + strlen(pattern);
  char buffer[PATBUFSIZE];
  for(;;)
    {
    int ellength;
    char *p = end_of_line(pattern, eop, &ellength);
    if (ellength == 0)
      return compile_single_pattern(pattern, options, filename, count);
    sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern);
    pattern = p;
    if (!compile_single_pattern(buffer, options, filename, count))
      return FALSE;
    }
  }
else return compile_single_pattern(pattern, options, filename, count);
}



/*************************************************
*                Main program                    *
*************************************************/

/* Returns 0 if something matched, 1 if nothing matched, 2 after an error. */

int
main(int argc, char **argv)
{
int i, j;
int rc = 1;
int pcre_options = 0;
int cmd_pattern_count = 0;
int hint_count = 0;
int errptr;
BOOL only_one_at_top;
char *patterns[MAX_PATTERN_COUNT];
const char *locale_from = "--locale";
const char *error;

#ifdef SUPPORT_PCREGREP_JIT
pcre_jit_stack *jit_stack = NULL;
#endif

/* Set the default line ending value from the default in the PCRE library;
"lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf".
Note that the return values from CONFIG8(), though derived from the ASCII
codes, are the same in EBCDIC environments, so we must use the actual values
rather than escapes such as as '\r'. */

(void)CONFIG8(PCRE_CONFIG_NEWLINE, &i);
switch(i)
  {
  default:               newline = (char *)"lf"; break;
  case 13:               newline = (char *)"cr"; break;
  case (13 << 8) | 10:   newline = (char *)"crlf"; break;
  case -1:               newline = (char *)"any"; break;
  case -2:               newline = (char *)"anycrlf"; break;
  }

/* Process the options */

for (i = 1; i < argc; i++)
  {
  option_item *op = NULL;
  char *option_data = (char *)"";    /* default to keep compiler happy */
  BOOL longop;
  BOOL longopwasequals = FALSE;

  if (argv[i][0] != '-') break;

  /* If we hit an argument that is just "-", it may be a reference to STDIN,
  but only if we have previously had -e or -f to define the patterns. */

  if (argv[i][1] == 0)
    {
    if (pattern_filename != NULL || pattern_count > 0) break;
      else pcregrep_exit(usage(2));
    }

  /* Handle a long name option, or -- to terminate the options */

  if (argv[i][1] == '-')
    {
    char *arg = argv[i] + 2;
    char *argequals = strchr(arg, '=');

    if (*arg == 0)    /* -- terminates options */
      {
      i++;
      break;                /* out of the options-handling loop */
      }

    longop = TRUE;

    /* Some long options have data that follows after =, for example file=name.
    Some options have variations in the long name spelling: specifically, we
    allow "regexp" because GNU grep allows it, though I personally go along
    with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".
    These options are entered in the table as "regex(p)". Options can be in
    both these categories. */

    for (op = optionlist; op->one_char != 0; op++)
      {
      char *opbra = strchr(op->long_name, '(');
      char *equals = strchr(op->long_name, '=');

      /* Handle options with only one spelling of the name */

      if (opbra == NULL)     /* Does not contain '(' */
        {
        if (equals == NULL)  /* Not thing=data case */
          {
          if (strcmp(arg, op->long_name) == 0) break;
          }
        else                 /* Special case xxx=data */
          {
          int oplen = (int)(equals - op->long_name);
          int arglen = (argequals == NULL)?
            (int)strlen(arg) : (int)(argequals - arg);
          if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)
            {
            option_data = arg + arglen;
            if (*option_data == '=')
              {
              option_data++;
              longopwasequals = TRUE;
              }
            break;
            }
          }
        }

      /* Handle options with an alternate spelling of the name */

      else
        {
        char buff1[24];
        char buff2[24];

        int baselen = (int)(opbra - op->long_name);
        int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);
        int arglen = (argequals == NULL || equals == NULL)?
          (int)strlen(arg) : (int)(argequals - arg);

        sprintf(buff1, "%.*s", baselen, op->long_name);
        sprintf(buff2, "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1);

        if (strncmp(arg, buff1, arglen) == 0 ||
           strncmp(arg, buff2, arglen) == 0)
          {
          if (equals != NULL && argequals != NULL)
            {
            option_data = argequals;
            if (*option_data == '=')
              {
              option_data++;
              longopwasequals = TRUE;
              }
            }
          break;
          }
        }
      }

    if (op->one_char == 0)
      {
      fprintf(stderr, "PCREGREP: Unknown option %s\n", argv[i]);
      pcregrep_exit(usage(2));
      }
    }

  /* Jeffrey Friedl's debugging harness uses these additional options which
  are not in the right form for putting in the option table because they use
  only one hyphen, yet are more than one character long. By putting them
  separately here, they will not get displayed as part of the help() output,
  but I don't think Jeffrey will care about that. */

#ifdef JFRIEDL_DEBUG
  else if (strcmp(argv[i], "-pre") == 0) {
          jfriedl_prefix = argv[++i];
          continue;
  } else if (strcmp(argv[i], "-post") == 0) {
          jfriedl_postfix = argv[++i];
          continue;
  } else if (strcmp(argv[i], "-XT") == 0) {
          sscanf(argv[++i], "%d", &jfriedl_XT);
          continue;
  } else if (strcmp(argv[i], "-XR") == 0) {
          sscanf(argv[++i], "%d", &jfriedl_XR);
          continue;
  }
#endif


  /* One-char options; many that have no data may be in a single argument; we
  continue till we hit the last one or one that needs data. */

  else
    {
    char *s = argv[i] + 1;
    longop = FALSE;
    while (*s != 0)
      {
      for (op = optionlist; op->one_char != 0; op++)
        {
        if (*s == op->one_char) break;
        }
      if (op->one_char == 0)
        {
        fprintf(stderr, "PCREGREP: Unknown option letter '%c' in \"%s\"\n",
          *s, argv[i]);
        pcregrep_exit(usage(2));
        }

      /* Check for a single-character option that has data: OP_OP_NUMBER
      is used for one that either has a numerical number or defaults, i.e. the
      data is optional. If a digit follows, there is data; if not, carry on
      with other single-character options in the same string. */

      option_data = s+1;
      if (op->type == OP_OP_NUMBER)
        {
        if (isdigit((unsigned char)s[1])) break;
        }
      else   /* Check for end or a dataless option */
        {
        if (op->type != OP_NODATA || s[1] == 0) break;
        }

      /* Handle a single-character option with no data, then loop for the
      next character in the string. */

      pcre_options = handle_option(*s++, pcre_options);
      }
    }

  /* At this point we should have op pointing to a matched option. If the type
  is NO_DATA, it means that there is no data, and the option might set
  something in the PCRE options. */

  if (op->type == OP_NODATA)
    {
    pcre_options = handle_option(op->one_char, pcre_options);
    continue;
    }

  /* If the option type is OP_OP_STRING or OP_OP_NUMBER, it's an option that
  either has a value or defaults to something. It cannot have data in a
  separate item. At the moment, the only such options are "colo(u)r",
  "only-matching", and Jeffrey Friedl's special -S debugging option. */

  if (*option_data == 0 &&
      (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER))
    {
    switch (op->one_char)
      {
      case N_COLOUR:
      colour_option = (char *)"auto";
      break;

      case 'o':
      only_matching = 0;
      break;

#ifdef JFRIEDL_DEBUG
      case 'S':
      S_arg = 0;
      break;
#endif
      }
    continue;
    }

  /* Otherwise, find the data string for the option. */

  if (*option_data == 0)
    {
    if (i >= argc - 1 || longopwasequals)
      {
      fprintf(stderr, "PCREGREP: Data missing after %s\n", argv[i]);
      pcregrep_exit(usage(2));
      }
    option_data = argv[++i];
    }

  /* If the option type is OP_PATLIST, it's the -e option, which can be called
  multiple times to create a list of patterns. */

  if (op->type == OP_PATLIST)
    {
    if (cmd_pattern_count >= MAX_PATTERN_COUNT)
      {
      fprintf(stderr, "PCREGREP: Too many command-line patterns (max %d)\n",
        MAX_PATTERN_COUNT);
      return 2;
      }
    patterns[cmd_pattern_count++] = option_data;
    }

  /* Handle OP_BINARY_FILES */

  else if (op->type == OP_BINFILES)
    {
    if (strcmp(option_data, "binary") == 0)
      binary_files = BIN_BINARY;
    else if (strcmp(option_data, "without-match") == 0)
      binary_files = BIN_NOMATCH;
    else if (strcmp(option_data, "text") == 0)
      binary_files = BIN_TEXT;
    else
      {
      fprintf(stderr, "PCREGREP: unknown value \"%s\" for binary-files\n",
        option_data);
      pcregrep_exit(usage(2));
      }
    }

  /* Otherwise, deal with single string or numeric data values. */

  else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER &&
           op->type != OP_OP_NUMBER)
    {
    *((char **)op->dataptr) = option_data;
    }

  /* Avoid the use of strtoul() because SunOS4 doesn't have it. This is used
  only for unpicking arguments, so just keep it simple. */

  else
    {
    unsigned long int n = 0;
    char *endptr = option_data;
    while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;
    while (isdigit((unsigned char)(*endptr)))
      n = n * 10 + (int)(*endptr++ - '0');
    if (toupper(*endptr) == 'K')
      {
      n *= 1024;
      endptr++;
      }
    else if (toupper(*endptr) == 'M')
      {
      n *= 1024*1024;
      endptr++;
      }
    if (*endptr != 0)
      {
      if (longop)
        {
        char *equals = strchr(op->long_name, '=');
        int nlen = (equals == NULL)? (int)strlen(op->long_name) :
          (int)(equals - op->long_name);
        fprintf(stderr, "PCREGREP: Malformed number \"%s\" after --%.*s\n",
          option_data, nlen, op->long_name);
        }
      else
        fprintf(stderr, "PCREGREP: Malformed number \"%s\" after -%c\n",
          option_data, op->one_char);
      pcregrep_exit(usage(2));
      }
    if (op->type == OP_LONGNUMBER)
        *((unsigned long int *)op->dataptr) = n;
    else
        *((int *)op->dataptr) = n;
    }
  }

/* Options have been decoded. If -C was used, its value is used as a default
for -A and -B. */

if (both_context > 0)
  {
  if (after_context == 0) after_context = both_context;
  if (before_context == 0) before_context = both_context;
  }

/* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
However, the latter two set only_matching. */

if ((only_matching >= 0 && (file_offsets || line_offsets)) ||
    (file_offsets && line_offsets))
  {
  fprintf(stderr, "PCREGREP: Cannot mix --only-matching, --file-offsets "
    "and/or --line-offsets\n");
  pcregrep_exit(usage(2));
  }

if (file_offsets || line_offsets) only_matching = 0;

/* If a locale has not been provided as an option, see if the LC_CTYPE or
LC_ALL environment variable is set, and if so, use it. */

if (locale == NULL)
  {
  locale = getenv("LC_ALL");
  locale_from = "LCC_ALL";
  }

if (locale == NULL)
  {
  locale = getenv("LC_CTYPE");
  locale_from = "LC_CTYPE";
  }

/* If a locale has been provided, set it, and generate the tables the PCRE
needs. Otherwise, pcretables==NULL, which causes the use of default tables. */

if (locale != NULL)
  {
  if (setlocale(LC_CTYPE, locale) == NULL)
    {
    fprintf(stderr, "PCREGREP: Failed to set locale %s (obtained from %s)\n",
      locale, locale_from);
    return 2;
    }
  pcretables = MAKETAB8();
  }

/* Sort out colouring */

if (colour_option != NULL && strcmp(colour_option, "never") != 0)
  {
  if (strcmp(colour_option, "always") == 0) do_colour = TRUE;
  else if (strcmp(colour_option, "auto") == 0) do_colour = is_stdout_tty();
  else
    {
    fprintf(stderr, "PCREGREP: Unknown colour setting \"%s\"\n",
      colour_option);
    return 2;
    }
  if (do_colour)
    {
    char *cs = getenv("PCREGREP_COLOUR");
    if (cs == NULL) cs = getenv("PCREGREP_COLOR");
    if (cs != NULL) colour_string = cs;
    }
  }

/* Interpret the newline type; the default settings are Unix-like. */

if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0)
  {
  pcre_options |= PCRE_NEWLINE_CR;
  endlinetype = EL_CR;
  }
else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0)
  {
  pcre_options |= PCRE_NEWLINE_LF;
  endlinetype = EL_LF;
  }
else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0)
  {
  pcre_options |= PCRE_NEWLINE_CRLF;
  endlinetype = EL_CRLF;
  }
else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0)
  {
  pcre_options |= PCRE_NEWLINE_ANY;
  endlinetype = EL_ANY;
  }
else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0)
  {
  pcre_options |= PCRE_NEWLINE_ANYCRLF;
  endlinetype = EL_ANYCRLF;
  }
else
  {
  fprintf(stderr, "PCREGREP: Invalid newline specifier \"%s\"\n", newline);
  return 2;
  }

/* Interpret the text values for -d and -D */

if (dee_option != NULL)
  {
  if (strcmp(dee_option, "read") == 0) dee_action = dee_READ;
  else if (strcmp(dee_option, "recurse") == 0) dee_action = dee_RECURSE;
  else if (strcmp(dee_option, "skip") == 0) dee_action = dee_SKIP;
  else
    {
    fprintf(stderr, "PCREGREP: Invalid value \"%s\" for -d\n", dee_option);
    return 2;
    }
  }

if (DEE_option != NULL)
  {
  if (strcmp(DEE_option, "read") == 0) DEE_action = DEE_READ;
  else if (strcmp(DEE_option, "skip") == 0) DEE_action = DEE_SKIP;
  else
    {
    fprintf(stderr, "PCREGREP: Invalid value \"%s\" for -D\n", DEE_option);
    return 2;
    }
  }

/* Check the values for Jeffrey Friedl's debugging options. */

#ifdef JFRIEDL_DEBUG
if (S_arg > 9)
  {
  fprintf(stderr, "PCREGREP: bad value for -S option\n");
  return 2;
  }
if (jfriedl_XT != 0 || jfriedl_XR != 0)
  {
  if (jfriedl_XT == 0) jfriedl_XT = 1;
  if (jfriedl_XR == 0) jfriedl_XR = 1;
  }
#endif

/* Get memory for the main buffer, and to store the pattern and hints lists. */

bufsize = 3*bufthird;
main_buffer = (char *)malloc(bufsize);
pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));

if (main_buffer == NULL || pattern_list == NULL || hints_list == NULL)
  {
  fprintf(stderr, "PCREGREP: malloc failed\n");
  goto EXIT2;
  }

/* If no patterns were provided by -e, and there is no file provided by -f,
the first argument is the one and only pattern, and it must exist. */

if (cmd_pattern_count == 0 && pattern_filename == NULL)
  {
  if (i >= argc) return usage(2);
  patterns[cmd_pattern_count++] = argv[i++];
  }

/* Compile the patterns that were provided on the command line, either by
multiple uses of -e or as a single unkeyed pattern. */

for (j = 0; j < cmd_pattern_count; j++)
  {
  if (!compile_pattern(patterns[j], pcre_options, NULL,
       (j == 0 && cmd_pattern_count == 1)? 0 : j + 1))
    goto EXIT2;
  }

/* Compile the regular expressions that are provided in a file. */

if (pattern_filename != NULL)
  {
  int linenumber = 0;
  FILE *f;
  char *filename;
  char buffer[PATBUFSIZE];

  if (strcmp(pattern_filename, "-") == 0)
    {
    f = stdin;
    filename = stdin_name;
    }
  else
    {
    f = fopen(pattern_filename, "r");
    if (f == NULL)
      {
      fprintf(stderr, "PCREGREP: Failed to open %s: %s\n", pattern_filename,
        strerror(errno));
      goto EXIT2;
      }
    filename = pattern_filename;
    }

  while (fgets(buffer, PATBUFSIZE, f) != NULL)
    {
    char *s = buffer + (int)strlen(buffer);
    while (s > buffer && isspace((unsigned char)(s[-1]))) s--;
    *s = 0;
    linenumber++;
    if (buffer[0] == 0) continue;   /* Skip blank lines */
    if (!compile_pattern(buffer, pcre_options, filename, linenumber))
      goto EXIT2;
    }

  if (f != stdin) fclose(f);
  }

/* Study the regular expressions, as we will be running them many times. Unless
JIT has been explicitly disabled, arrange a stack for it to use. */

#ifdef SUPPORT_PCREGREP_JIT
if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0)
  jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024);
#endif

for (j = 0; j < pattern_count; j++)
  {
  hints_list[j] = STUDY8(pattern_list[j], study_options, &error);
  if (error != NULL)
    {
    char s[16];
    if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);
    fprintf(stderr, "PCREGREP: Error while studying regex%s: %s\n", s, error);
    goto EXIT2;
    }
  hint_count++;
#ifdef SUPPORT_PCREGREP_JIT
  if (jit_stack != NULL && hints_list[j] != NULL)
    pcre_assign_jit_stack(hints_list[j], NULL, jit_stack);
#endif
  }

/* If --match-limit or --recursion-limit was set, put the value(s) into the
pcre_extra block for each pattern. */

if (match_limit > 0 || match_limit_recursion > 0)
  {
  for (j = 0; j < pattern_count; j++)
    {
    if (hints_list[j] == NULL)
      {
      hints_list[j] = malloc(sizeof(pcre_extra));
      if (hints_list[j] == NULL)
        {
        fprintf(stderr, "PCREGREP: malloc failed\n");
        pcregrep_exit(2);
        }
      }
    if (match_limit > 0)
      {
      hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT;
      hints_list[j]->match_limit = match_limit;
      }
    if (match_limit_recursion > 0)
      {
      hints_list[j]->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
      hints_list[j]->match_limit_recursion = match_limit_recursion;
      }
    }
  }

/* If there are include or exclude patterns, compile them. */

if (exclude_pattern != NULL)
  {
  exclude_compiled = COMPILE8(exclude_pattern, 0, &error, &errptr,
    pcretables);
  if (exclude_compiled == NULL)
    {
    fprintf(stderr, "PCREGREP: Error in 'exclude' regex at offset %d: %s\n",
      errptr, error);
    goto EXIT2;
    }
  }

if (include_pattern != NULL)
  {
  include_compiled = COMPILE8(include_pattern, 0, &error, &errptr,
    pcretables);
  if (include_compiled == NULL)
    {
    fprintf(stderr, "PCREGREP: Error in 'include' regex at offset %d: %s\n",
      errptr, error);
    goto EXIT2;
    }
  }

if (exclude_dir_pattern != NULL)
  {
  exclude_dir_compiled = COMPILE8(exclude_dir_pattern, 0, &error, &errptr,
    pcretables);
  if (exclude_dir_compiled == NULL)
    {
    fprintf(stderr, "PCREGREP: Error in 'exclude_dir' regex at offset %d: %s\n",
      errptr, error);
    goto EXIT2;
    }
  }

if (include_dir_pattern != NULL)
  {
  include_dir_compiled = COMPILE8(include_dir_pattern, 0, &error, &errptr,
    pcretables);
  if (include_dir_compiled == NULL)
    {
    fprintf(stderr, "PCREGREP: Error in 'include_dir' regex at offset %d: %s\n",
      errptr, error);
    goto EXIT2;
    }
  }

/* If a file that contains a list of files to search has been specified, read
it line by line and search the given files. Otherwise, if there are no further
arguments, do the business on stdin and exit. */

if (file_list != NULL)
  {
  char buffer[PATBUFSIZE];
  FILE *fl;
  if (strcmp(file_list, "-") == 0) fl = stdin; else
    {
    fl = fopen(file_list, "r");
    if (fl == NULL)
      {
      fprintf(stderr, "PCREGREP: Failed to open %s: %s\n", file_list,
        strerror(errno));
      goto EXIT2;
      }
    }
  while (fgets(buffer, PATBUFSIZE, fl) != NULL)
    {
    int frc;
    char *end = buffer + (int)strlen(buffer);
    while (end > buffer && isspace(end[-1])) end--;
    *end = 0;
    if (*buffer != 0)
      {
      frc = grep_or_recurse(buffer, dee_action == dee_RECURSE, FALSE);
      if (frc > 1) rc = frc;
        else if (frc == 0 && rc == 1) rc = 0;
      }
    }
  if (fl != stdin) fclose (fl);
  }

/* Do this only if there was no file list (and no file arguments). */

else if (i >= argc)
  {
  rc = PCREGREP(stdin, FR_PLAIN, stdin_name,
    (filenames > FN_DEFAULT)? stdin_name : NULL);
  goto EXIT;
  }

/* After handling file-list or if there are remaining arguments, work through
them as files or directories. Pass in the fact that there is only one argument
at top level - this suppresses the file name if the argument is not a directory
and filenames are not otherwise forced. */

only_one_at_top = i == argc - 1 && file_list == NULL;

for (; i < argc; i++)
  {
  int frc = grep_or_recurse(argv[i], dee_action == dee_RECURSE,
    only_one_at_top);
  if (frc > 1) rc = frc;
    else if (frc == 0 && rc == 1) rc = 0;
  }

EXIT:
#ifdef SUPPORT_PCREGREP_JIT
if (jit_stack != NULL) pcre_jit_stack_free(jit_stack);
#endif
if (main_buffer != NULL) free(main_buffer);
if (pattern_list != NULL)
  {
  for (i = 0; i < pattern_count; i++) free(pattern_list[i]);
  free(pattern_list);
  }
if (hints_list != NULL)
  {
  for (i = 0; i < hint_count; i++)
    {
    if (hints_list[i] != NULL) pcre_free_study(hints_list[i]);
    }
  free(hints_list);
  }
pcregrep_exit(rc);

EXIT2:
rc = 2;
goto EXIT;
}

/* End of PCREGREP */
/*autoconv-0001 C:\projects\pcre-8.31\pcregrep.c converted to PCREGREP*/
/*autoconv-0013 PCREGREP line: 2 pcregrep replaced by PCREGREP*/
/*autoconv-0010 PCREGREP line: 41 added HAVE_CONFIG_H*/
/*autoconv-0011 PCREGREP line: 44 config.h replaced by CONFIG.h*/
/*autoconv-0011 PCREGREP line: 69 pcre.h replaced by PCRE.h*/
/*autoconv-0013 PCREGREP line: 266 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 345 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 348 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 486 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 976 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 997 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1001 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1001 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1011 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1050 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1137 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1154 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1155 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1197 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1632 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1654 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1668 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1672 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1678 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1682 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGREP line: 1720 pcregrep replaced by PCREGREP*/
/*autoconv-0015 PCREGREP line: 1749 fopen "rb" replaced by "r"*/
/*autoconv-0013 PCREGREP line: 1759 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1766 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1794 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1807 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1823 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1829 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1846 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1865 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1945 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 1945 pcre_version replaced by VERSION8*/
/*autoconv-0013 PCREGREP line: 1950 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2012 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2020 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCREGREP line: 2035 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2038 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2043 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2120 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCREGREP line: 2124 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCREGREP line: 2241 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2284 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2354 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2367 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2386 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2427 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2431 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2457 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2486 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2490 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0013 PCREGREP line: 2501 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2542 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2555 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2566 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2576 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2595 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2637 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2668 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCREGREP line: 2673 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2695 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2716 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCREGREP line: 2720 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2728 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCREGREP line: 2732 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2740 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCREGREP line: 2744 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2752 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCREGREP line: 2756 pcregrep replaced by PCREGREP*/
/*autoconv-0015 PCREGREP line: 2772 fopen "rb" replaced by "r"*/
/*autoconv-0013 PCREGREP line: 2775 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2800 pcregrep replaced by PCREGREP*/
/*autoconv-0013 PCREGREP line: 2845 pcregrep replaced by PCREGREP*/
./ ADD NAME=DFAEXEC8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language (but see
below for why this module is different).

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

/* This module contains the external function DFAEXEC8(), which is an
alternative matching function that uses a sort of DFA algorithm (not a true
FSM). This is NOT Perl-compatible, but it has advantages in certain
applications. */


/* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved
the performance of his patterns greatly. I could not use it as it stood, as it
was not thread safe, and made assumptions about pattern sizes. Also, it caused
test 7 to loop, and test 9 to crash with a segfault.

The issue is the check for duplicate states, which is done by a simple linear
search up the state list. (Grep for "duplicate" below to find the code.) For
many patterns, there will never be many states active at one time, so a simple
linear search is fine. In patterns that have many active states, it might be a
bottleneck. The suggested code used an indexing scheme to remember which states
had previously been used for each character, and avoided the linear search when
it knew there was no chance of a duplicate. This was implemented when adding
states to the state lists.

I wrote some thread-safe, not-limited code to try something similar at the time
of checking for duplicates (instead of when adding states), using index vectors
on the stack. It did give a 13% improvement with one specially constructed
pattern for certain subject strings, but on other strings and on many of the
simpler patterns in the test suite it did worse. The major problem, I think,
was the extra time to initialize the index. This had to be done for each call
of internal_dfa_exec(). (The supplied patch used a static vector, initialized
only once - I suspect this was the cause of the problems with the tests.)

Overall, I concluded that the gains in some cases did not outweigh the losses
in others, so I abandoned this code. */



#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#define NLBLOCK md             /* Block containing newline information */
#define PSSTART start_subject  /* Field containing processed string start */
#define PSEND   end_subject    /* Field containing processed string end */

#include "INTERNA8.h"


/* For use to indent debugging output */

#define SP "                   "


/*************************************************
*      Code parameters and static tables         *
*************************************************/

/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes
into others, under special conditions. A gap of 20 between the blocks should be
enough. The resulting opcodes don't have to be less than 256 because they are
never stored, so we push them well clear of the normal opcodes. */

#define OP_PROP_EXTRA       300
#define OP_EXTUNI_EXTRA     320
#define OP_ANYNL_EXTRA      340
#define OP_HSPACE_EXTRA     360
#define OP_VSPACE_EXTRA     380


/* This table identifies those opcodes that are followed immediately by a
character that is to be tested in some way. This makes it possible to
centralize the loading of these characters. In the case of Type * etc, the
"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a
small value. Non-zero values in the table are the offsets from the opcode where
the character is to be found. ***NOTE*** If the start of this table is
modified, the three tables that follow must also be modified. */

static const pcre_uint8 coptable[] = {
  0,                             /* End                                    */
  0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
  0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */
  0, 0, 0,                       /* Any, AllAny, Anybyte                   */
  0, 0,                          /* \P, \p                                 */
  0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
  0,                             /* \X                                     */
  0, 0, 0, 0, 0, 0,              /* \Z, \z, , M, $, $M                   */
  1,                             /* Char                                   */
  1,                             /* Chari                                  */
  1,                             /* not                                    */
  1,                             /* noti                                   */
  /* Positive single-char repeats                                          */
  1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto, minupto                          */
  1+IMM2_SIZE,                   /* exact                                  */
  1, 1, 1, 1+IMM2_SIZE,          /* *+, ++, ?+, upto+                      */
  1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto I, minupto I                      */
  1+IMM2_SIZE,                   /* exact I                                */
  1, 1, 1, 1+IMM2_SIZE,          /* *+I, ++I, ?+I, upto+I                  */
  /* Negative single-char repeats - only for chars < 256                   */
  1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto, minupto                      */
  1+IMM2_SIZE,                   /* NOT exact                              */
  1, 1, 1, 1+IMM2_SIZE,          /* NOT *+, ++, ?+, upto+                  */
  1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto I, minupto I                  */
  1+IMM2_SIZE,                   /* NOT exact I                            */
  1, 1, 1, 1+IMM2_SIZE,          /* NOT *+I, ++I, ?+I, upto+I              */
  /* Positive type repeats                                                 */
  1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
  1+IMM2_SIZE, 1+IMM2_SIZE,      /* Type upto, minupto                     */
  1+IMM2_SIZE,                   /* Type exact                             */
  1, 1, 1, 1+IMM2_SIZE,          /* Type *+, ++, ?+, upto+                 */
  /* Character class & ref repeats                                         */
  0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */
  0, 0,                          /* CRRANGE, CRMINRANGE                    */
  0,                             /* CLASS                                  */
  0,                             /* NCLASS                                 */
  0,                             /* XCLASS - variable length               */
  0,                             /* REF                                    */
  0,                             /* REFI                                   */
  0,                             /* RECURSE                                */
  0,                             /* CALLOUT                                */
  0,                             /* Alt                                    */
  0,                             /* Ket                                    */
  0,                             /* KetRmax                                */
  0,                             /* KetRmin                                */
  0,                             /* KetRpos                                */
  0,                             /* Reverse                                */
  0,                             /* Assert                                 */
  0,                             /* Assert not                             */
  0,                             /* Assert behind                          */
  0,                             /* Assert behind not                      */
  0, 0,                          /* ONCE, ONCE_NC                          */
  0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
  0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
  0, 0,                          /* CREF, NCREF                            */
  0, 0,                          /* RREF, NRREF                            */
  0,                             /* DEF                                    */
  0, 0, 0,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */
  0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG                 */
  0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG         */
  0, 0, 0, 0,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */
  0, 0                           /* CLOSE, SKIPZERO  */
};

/* This table identifies those opcodes that inspect a character. It is used to
remember the fact that a character could have been inspected when the end of
the subject is reached. ***NOTE*** If the start of this table is modified, the
two tables that follow must also be modified. */

static const pcre_uint8 poptable[] = {
  0,                             /* End                                    */
  0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */
  1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */
  1, 1, 1,                       /* Any, AllAny, Anybyte                   */
  1, 1,                          /* \P, \p                                 */
  1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */
  1,                             /* \X                                     */
  0, 0, 0, 0, 0, 0,              /* \Z, \z, , M, $, $M                   */
  1,                             /* Char                                   */
  1,                             /* Chari                                  */
  1,                             /* not                                    */
  1,                             /* noti                                   */
  /* Positive single-char repeats                                          */
  1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
  1, 1, 1,                       /* upto, minupto, exact                   */
  1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */
  1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
  1, 1, 1,                       /* upto I, minupto I, exact I             */
  1, 1, 1, 1,                    /* *+I, ++I, ?+I, upto+I                  */
  /* Negative single-char repeats - only for chars < 256                   */
  1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
  1, 1, 1,                       /* NOT upto, minupto, exact               */
  1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */
  1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
  1, 1, 1,                       /* NOT upto I, minupto I, exact I         */
  1, 1, 1, 1,                    /* NOT *+I, ++I, ?+I, upto+I              */
  /* Positive type repeats                                                 */
  1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
  1, 1, 1,                       /* Type upto, minupto, exact              */
  1, 1, 1, 1,                    /* Type *+, ++, ?+, upto+                 */
  /* Character class & ref repeats                                         */
  1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
  1, 1,                          /* CRRANGE, CRMINRANGE                    */
  1,                             /* CLASS                                  */
  1,                             /* NCLASS                                 */
  1,                             /* XCLASS - variable length               */
  0,                             /* REF                                    */
  0,                             /* REFI                                   */
  0,                             /* RECURSE                                */
  0,                             /* CALLOUT                                */
  0,                             /* Alt                                    */
  0,                             /* Ket                                    */
  0,                             /* KetRmax                                */
  0,                             /* KetRmin                                */
  0,                             /* KetRpos                                */
  0,                             /* Reverse                                */
  0,                             /* Assert                                 */
  0,                             /* Assert not                             */
  0,                             /* Assert behind                          */
  0,                             /* Assert behind not                      */
  0, 0,                          /* ONCE, ONCE_NC                          */
  0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
  0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
  0, 0,                          /* CREF, NCREF                            */
  0, 0,                          /* RREF, NRREF                            */
  0,                             /* DEF                                    */
  0, 0, 0,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */
  0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG                 */
  0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG         */
  0, 0, 0, 0,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */
  0, 0                           /* CLOSE, SKIPZERO                        */
};

/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
and \w */

static const pcre_uint8 toptable1[] = {
  0, 0, 0, 0, 0, 0,
  ctype_digit, ctype_digit,
  ctype_space, ctype_space,
  ctype_word,  ctype_word,
  0, 0                            /* OP_ANY, OP_ALLANY */
};

static const pcre_uint8 toptable2[] = {
  0, 0, 0, 0, 0, 0,
  ctype_digit, 0,
  ctype_space, 0,
  ctype_word,  0,
  1, 1                            /* OP_ANY, OP_ALLANY */
};


/* Structure for holding data about a particular state, which is in effect the
current data for an active path through the match tree. It must consist
entirely of ints because the working vector we are passed, and which we put
these structures in, is a vector of ints. */

typedef struct stateblock {
  int offset;                     /* Offset to opcode */
  int count;                      /* Count for repeats */
  int data;                       /* Some use extra data */
} stateblock;

#define INTS_PER_STATEBLOCK  (int)(sizeof(stateblock)/sizeof(int))


#ifdef PCRE_DEBUG
/*************************************************
*             Print character string             *
*************************************************/

/* Character string printing function for debugging.

Arguments:
  p            points to string
  length       number of bytes
  f            where to print

Returns:       nothing
*/

static void
pchars(const pcre_uchar *p, int length, FILE *f)
{
int c;
while (length-- > 0)
  {
  if (isprint(c = *(p++)))
    fprintf(f, "%c", c);
  else
    fprintf(f, "\\x%02x", c);
  }
}
#endif



/*************************************************
*    Execute a Regular Expression - DFA engine   *
*************************************************/

/* This internal function applies a compiled pattern to a subject string,
starting at a given point, using a DFA engine. This function is called from the
external one, possibly multiple times if the pattern is not anchored. The
function calls itself recursively for some kinds of subpattern.

Arguments:
  md                the match_data block with fixed information
  this_start_code   the opening bracket of this subexpression's code
  current_subject   where we currently are in the subject string
  start_offset      start offset in the subject string
  offsets           vector to contain the matching string offsets
  offsetcount       size of same
  workspace         vector of workspace
  wscount           size of same
  rlevel            function call recursion level

Returns:            > 0 => number of match offset pairs placed in offsets
                    = 0 => offsets overflowed; longest matches are present
                     -1 => failed to match
                   < -1 => some kind of unexpected problem

The following macros are used for adding states to the two state vectors (one
for the current character, one for the following character). */

#define ADD_ACTIVE(x,y) \
  if (active_count++ < wscount) \
    { \
    next_active_state->offset = (x); \
    next_active_state->count  = (y); \
    next_active_state++; \
    DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
    } \
  else return PCRE_ERROR_DFA_WSSIZE

#define ADD_ACTIVE_DATA(x,y,z) \
  if (active_count++ < wscount) \
    { \
    next_active_state->offset = (x); \
    next_active_state->count  = (y); \
    next_active_state->data   = (z); \
    next_active_state++; \
    DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
    } \
  else return PCRE_ERROR_DFA_WSSIZE

#define ADD_NEW(x,y) \
  if (new_count++ < wscount) \
    { \
    next_new_state->offset = (x); \
    next_new_state->count  = (y); \
    next_new_state++; \
    DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
    } \
  else return PCRE_ERROR_DFA_WSSIZE

#define ADD_NEW_DATA(x,y,z) \
  if (new_count++ < wscount) \
    { \
    next_new_state->offset = (x); \
    next_new_state->count  = (y); \
    next_new_state->data   = (z); \
    next_new_state++; \
    DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \
      (x), (y), (z), __LINE__)); \
    } \
  else return PCRE_ERROR_DFA_WSSIZE

/* And now, here is the code */

static int
internal_dfa_exec(
  dfa_match_data *md,
  const pcre_uchar *this_start_code,
  const pcre_uchar *current_subject,
  int start_offset,
  int *offsets,
  int offsetcount,
  int *workspace,
  int wscount,
  int  rlevel)
{
stateblock *active_states, *new_states, *temp_states;
stateblock *next_active_state, *next_new_state;

const pcre_uint8 *ctypes, *lcc, *fcc;
const pcre_uchar *ptr;
const pcre_uchar *end_code, *first_op;

dfa_recursion_info new_recursive;

int active_count, new_count, match_count;

/* Some fields in the md block are frequently referenced, so we load them into
independent variables in the hope that this will perform better. */

const pcre_uchar *start_subject = md->start_subject;
const pcre_uchar *end_subject = md->end_subject;
const pcre_uchar *start_code = md->start_code;

#ifdef SUPPORT_UTF
BOOL utf = (md->poptions & PCRE_UTF8) != 0;
#else
BOOL utf = FALSE;
#endif

BOOL reset_could_continue = FALSE;

rlevel++;
offsetcount &= (-2);

wscount -= 2;
wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) /
          (2 * INTS_PER_STATEBLOCK);

DPRINTF(("\n%.*s---------------------\n"
  "%.*sCall to internal_dfa_exec f=%d\n",
  rlevel*2-2, SP, rlevel*2-2, SP, rlevel));

ctypes = md->tables + ctypes_offset;
lcc = md->tables + lcc_offset;
fcc = md->tables + fcc_offset;

match_count = PCRE_ERROR_NOMATCH;   /* A negative number */

active_states = (stateblock *)(workspace + 2);
next_new_state = new_states = active_states + wscount;
new_count = 0;

first_op = this_start_code + 1 + LINK_SIZE +
  ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
    *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
    ? IMM2_SIZE:0);

/* The first thing in any (sub) pattern is a bracket of some sort. Push all
the alternative states onto the list, and find out where the end is. This
makes is possible to use this function recursively, when we want to stop at a
matching internal ket rather than at the end.

If the first opcode in the first alternative is OP_REVERSE, we are dealing with
a backward assertion. In that case, we have to find out the maximum amount to
move back, and set up each alternative appropriately. */

if (*first_op == OP_REVERSE)
  {
  int max_back = 0;
  int gone_back;

  end_code = this_start_code;
  do
    {
    int back = GET(end_code, 2+LINK_SIZE);
    if (back > max_back) max_back = back;
    end_code += GET(end_code, 1);
    }
  while (*end_code == OP_ALT);

  /* If we can't go back the amount required for the longest lookbehind
  pattern, go back as far as we can; some alternatives may still be viable. */

#ifdef SUPPORT_UTF
  /* In character mode we have to step back character by character */

  if (utf)
    {
    for (gone_back = 0; gone_back < max_back; gone_back++)
      {
      if (current_subject <= start_subject) break;
      current_subject--;
      ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--);
      }
    }
  else
#endif

  /* In byte-mode we can do this quickly. */

    {
    gone_back = (current_subject - max_back < start_subject)?
      (int)(current_subject - start_subject) : max_back;
    current_subject -= gone_back;
    }

  /* Save the earliest consulted character */

  if (current_subject < md->start_used_ptr)
    md->start_used_ptr = current_subject;

  /* Now we can process the individual branches. */

  end_code = this_start_code;
  do
    {
    int back = GET(end_code, 2+LINK_SIZE);
    if (back <= gone_back)
      {
      int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE);
      ADD_NEW_DATA(-bstate, 0, gone_back - back);
      }
    end_code += GET(end_code, 1);
    }
  while (*end_code == OP_ALT);
 }

/* This is the code for a "normal" subpattern (not a backward assertion). The
start of a whole pattern is always one of these. If we are at the top level,
we may be asked to restart matching from the same point that we reached for a
previous partial match. We still have to scan through the top-level branches to
find the end state. */

else
  {
  end_code = this_start_code;

  /* Restarting */

  if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0)
    {
    do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT);
    new_count = workspace[1];
    if (!workspace[0])
      memcpy(new_states, active_states, new_count * sizeof(stateblock));
    }

  /* Not restarting */

  else
    {
    int length = 1 + LINK_SIZE +
      ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
        *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
        ? IMM2_SIZE:0);
    do
      {
      ADD_NEW((int)(end_code - start_code + length), 0);
      end_code += GET(end_code, 1);
      length = 1 + LINK_SIZE;
      }
    while (*end_code == OP_ALT);
    }
  }

workspace[0] = 0;    /* Bit indicating which vector is current */

DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code)));

/* Loop for scanning the subject */

ptr = current_subject;
for (;;)
  {
  int i, j;
  int clen, dlen;
  unsigned int c, d;
  int forced_fail = 0;
  BOOL partial_newline = FALSE;
  BOOL could_continue = reset_could_continue;
  reset_could_continue = FALSE;

  /* Make the new state list into the active state list and empty the
  new state list. */

  temp_states = active_states;
  active_states = new_states;
  new_states = temp_states;
  active_count = new_count;
  new_count = 0;

  workspace[0] = 1;              /* Remember for the restarting feature */
  workspace[1] = active_count;

#ifdef PCRE_DEBUG
  printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);
  pchars(ptr, STRLEN_UC(ptr), stdout);
  printf("\"\n");

  printf("%.*sActive states: ", rlevel*2-2, SP);
  for (i = 0; i < active_count; i++)
    printf("%d/%d ", active_states[i].offset, active_states[i].count);
  printf("\n");
#endif

  /* Set the pointers for adding new states */

  next_active_state = active_states + active_count;
  next_new_state = new_states;

  /* Load the current character from the subject outside the loop, as many
  different states may want to look at it, and we assume that at least one
  will. */

  if (ptr < end_subject)
    {
    clen = 1;        /* Number of data items in the character */
#ifdef SUPPORT_UTF
    if (utf) { GETCHARLEN(c, ptr, clen); } else
#endif  /* SUPPORT_UTF */
    c = *ptr;
    }
  else
    {
    clen = 0;        /* This indicates the end of the subject */
    c = NOTACHAR;    /* This value should never actually be used */
    }

  /* Scan up the active states and act on each one. The result of an action
  may be to add more states to the currently active list (e.g. on hitting a
  parenthesis) or it may be to put states on the new list, for considering
  when we move the character pointer on. */

  for (i = 0; i < active_count; i++)
    {
    stateblock *current_state = active_states + i;
    BOOL caseless = FALSE;
    const pcre_uchar *code;
    int state_offset = current_state->offset;
    int count, codevalue, rrc;

#ifdef PCRE_DEBUG
    printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);
    if (clen == 0) printf("EOL\n");
      else if (c > 32 && c < 127) printf("'%c'\n", c);
        else printf("0x%02x\n", c);
#endif

    /* A negative offset is a special case meaning "hold off going to this
    (negated) state until the number of characters in the data field have
    been skipped". If the could_continue flag was passed over from a previous
    state, arrange for it to passed on. */

    if (state_offset < 0)
      {
      if (current_state->data > 0)
        {
        DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
        ADD_NEW_DATA(state_offset, current_state->count,
          current_state->data - 1);
        if (could_continue) reset_could_continue = TRUE;
        continue;
        }
      else
        {
        current_state->offset = state_offset = -state_offset;
        }
      }

    /* Check for a duplicate state with the same count, and skip if found.
    See the note at the head of this module about the possibility of improving
    performance here. */

    for (j = 0; j < i; j++)
      {
      if (active_states[j].offset == state_offset &&
          active_states[j].count == current_state->count)
        {
        DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP));
        goto NEXT_ACTIVE_STATE;
        }
      }

    /* The state offset is the offset to the opcode */

    code = start_code + state_offset;
    codevalue = *code;

    /* If this opcode inspects a character, but we are at the end of the
    subject, remember the fact for use when testing for a partial match. */

    if (clen == 0 && poptable[codevalue] != 0)
      could_continue = TRUE;

    /* If this opcode is followed by an inline character, load it. It is
    tempting to test for the presence of a subject character here, but that
    is wrong, because sometimes zero repetitions of the subject are
    permitted.

    We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
    argument that is not a data character - but is always one byte long because
    the values are small. We have to take special action to deal with  \P, \p,
    \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert
    these ones to new opcodes. */

    if (coptable[codevalue] > 0)
      {
      dlen = 1;
#ifdef SUPPORT_UTF
      if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
#endif  /* SUPPORT_UTF */
      d = code[coptable[codevalue]];
      if (codevalue >= OP_TYPESTAR)
        {
        switch(d)
          {
          case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM;
          case OP_NOTPROP:
          case OP_PROP: codevalue += OP_PROP_EXTRA; break;
          case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
          case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;
          case OP_NOT_HSPACE:
          case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;
          case OP_NOT_VSPACE:
          case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;
          default: break;
          }
        }
      }
    else
      {
      dlen = 0;         /* Not strictly necessary, but compilers moan */
      d = NOTACHAR;     /* if these variables are not set. */
      }


    /* Now process the individual opcodes */

    switch (codevalue)
      {
/* ========================================================================== */
      /* These cases are never obeyed. This is a fudge that causes a compile-
      time error if the vectors coptable or poptable, which are indexed by
      opcode, are not the correct length. It seems to be the only way to do
      such a check at compile time, as the sizeof() operator does not work
      in the C preprocessor. */

      case OP_TABLE_LENGTH:
      case OP_TABLE_LENGTH +
        ((sizeof(coptable) == OP_TABLE_LENGTH) &&
         (sizeof(poptable) == OP_TABLE_LENGTH)):
      break;

/* ========================================================================== */
      /* Reached a closing bracket. If not at the end of the pattern, carry
      on with the next opcode. For repeating opcodes, also add the repeat
      state. Note that KETRPOS will always be encountered at the end of the
      subpattern, because the possessive subpattern repeats are always handled
      using recursive calls. Thus, it never adds any new states.

      At the end of the (sub)pattern, unless we have an empty string and
      PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the
      start of the subject, save the match data, shifting up all previous
      matches so we always have the longest first. */

      case OP_KET:
      case OP_KETRMIN:
      case OP_KETRMAX:
      case OP_KETRPOS:
      if (code != end_code)
        {
        ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);
        if (codevalue != OP_KET)
          {
          ADD_ACTIVE(state_offset - GET(code, 1), 0);
          }
        }
      else
        {
        if (ptr > current_subject ||
            ((md->moptions & PCRE_NOTEMPTY) == 0 &&
              ((md->moptions & PCRE_NOTEMPTY_ATSTART) == 0 ||
                current_subject > start_subject + md->start_offset)))
          {
          if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
            else if (match_count > 0 && ++match_count * 2 > offsetcount)
              match_count = 0;
          count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
          if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
          if (offsetcount >= 2)
            {
            offsets[0] = (int)(current_subject - start_subject);
            offsets[1] = (int)(ptr - start_subject);
            DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
              offsets[1] - offsets[0], (char *)current_subject));
            }
          if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
            {
            DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
              "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,
              match_count, rlevel*2-2, SP));
            return match_count;
            }
          }
        }
      break;

/* ========================================================================== */
      /* These opcodes add to the current list of states without looking
      at the current character. */

      /*-----------------------------------------------------------------*/
      case OP_ALT:
      do { code += GET(code, 1); } while (*code == OP_ALT);
      ADD_ACTIVE((int)(code - start_code), 0);
      break;

      /*-----------------------------------------------------------------*/
      case OP_BRA:
      case OP_SBRA:
      do
        {
        ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
        code += GET(code, 1);
        }
      while (*code == OP_ALT);
      break;

      /*-----------------------------------------------------------------*/
      case OP_CBRA:
      case OP_SCBRA:
      ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE),  0);
      code += GET(code, 1);
      while (*code == OP_ALT)
        {
        ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE),  0);
        code += GET(code, 1);
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_BRAZERO:
      case OP_BRAMINZERO:
      ADD_ACTIVE(state_offset + 1, 0);
      code += 1 + GET(code, 2);
      while (*code == OP_ALT) code += GET(code, 1);
      ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
      break;

      /*-----------------------------------------------------------------*/
      case OP_SKIPZERO:
      code += 1 + GET(code, 2);
      while (*code == OP_ALT) code += GET(code, 1);
      ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
      break;

      /*-----------------------------------------------------------------*/
      case OP_CIRC:
      if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0)
        { ADD_ACTIVE(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_CIRCM:
      if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
          (ptr != end_subject && WAS_NEWLINE(ptr)))
        { ADD_ACTIVE(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_EOD:
      if (ptr >= end_subject)
        {
        if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
          could_continue = TRUE;
        else { ADD_ACTIVE(state_offset + 1, 0); }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_SOD:
      if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_SOM:
      if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); }
      break;


/* ========================================================================== */
      /* These opcodes inspect the next subject character, and sometimes
      the previous one as well, but do not have an argument. The variable
      clen contains the length of the current character and is zero if we are
      at the end of the subject. */

      /*-----------------------------------------------------------------*/
      case OP_ANY:
      if (clen > 0 && !IS_NEWLINE(ptr))
        {
        if (ptr + 1 >= md->end_subject &&
            (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            c == NLBLOCK->nl[0])
          {
          could_continue = partial_newline = TRUE;
          }
        else
          {
          ADD_NEW(state_offset + 1, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_ALLANY:
      if (clen > 0)
        { ADD_NEW(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_EODN:
      if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
        could_continue = TRUE;
      else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
        { ADD_ACTIVE(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_DOLL:
      if ((md->moptions & PCRE_NOTEOL) == 0)
        {
        if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
          could_continue = TRUE;
        else if (clen == 0 ||
            ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
               (ptr == end_subject - md->nllen)
            ))
          { ADD_ACTIVE(state_offset + 1, 0); }
        else if (ptr + 1 >= md->end_subject &&
                 (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
                 NLBLOCK->nltype == NLTYPE_FIXED &&
                 NLBLOCK->nllen == 2 &&
                 c == NLBLOCK->nl[0])
          {
          if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
            {
            reset_could_continue = TRUE;
            ADD_NEW_DATA(-(state_offset + 1), 0, 1);
            }
          else could_continue = partial_newline = TRUE;
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_DOLLM:
      if ((md->moptions & PCRE_NOTEOL) == 0)
        {
        if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
          could_continue = TRUE;
        else if (clen == 0 ||
            ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
          { ADD_ACTIVE(state_offset + 1, 0); }
        else if (ptr + 1 >= md->end_subject &&
                 (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
                 NLBLOCK->nltype == NLTYPE_FIXED &&
                 NLBLOCK->nllen == 2 &&
                 c == NLBLOCK->nl[0])
          {
          if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
            {
            reset_could_continue = TRUE;
            ADD_NEW_DATA(-(state_offset + 1), 0, 1);
            }
          else could_continue = partial_newline = TRUE;
          }
        }
      else if (IS_NEWLINE(ptr))
        { ADD_ACTIVE(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/

      case OP_DIGIT:
      case OP_WHITESPACE:
      case OP_WORDCHAR:
      if (clen > 0 && c < 256 &&
            ((ctypes[c] & toptable1[codevalue])  toptable2[codevalue]) != 0)
        { ADD_NEW(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_NOT_DIGIT:
      case OP_NOT_WHITESPACE:
      case OP_NOT_WORDCHAR:
      if (clen > 0 && (c >= 256 ||
            ((ctypes[c] & toptable1[codevalue])  toptable2[codevalue]) != 0))
        { ADD_NEW(state_offset + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_WORD_BOUNDARY:
      case OP_NOT_WORD_BOUNDARY:
        {
        int left_word, right_word;

        if (ptr > start_subject)
          {
          const pcre_uchar *temp = ptr - 1;
          if (temp < md->start_used_ptr) md->start_used_ptr = temp;
#ifdef SUPPORT_UTF
          if (utf) { BACKCHAR(temp); }
#endif
          GETCHARTEST(d, temp);
#ifdef SUPPORT_UCP
          if ((md->poptions & PCRE_UCP) != 0)
            {
            if (d == '_') left_word = TRUE; else
              {
              int cat = UCD_CATEGORY(d);
              left_word = (cat == ucp_L || cat == ucp_N);
              }
            }
          else
#endif
          left_word = d < 256 && (ctypes[d] & ctype_word) != 0;
          }
        else left_word = FALSE;

        if (clen > 0)
          {
#ifdef SUPPORT_UCP
          if ((md->poptions & PCRE_UCP) != 0)
            {
            if (c == '_') right_word = TRUE; else
              {
              int cat = UCD_CATEGORY(c);
              right_word = (cat == ucp_L || cat == ucp_N);
              }
            }
          else
#endif
          right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
          }
        else right_word = FALSE;

        if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
          { ADD_ACTIVE(state_offset + 1, 0); }
        }
      break;


      /*-----------------------------------------------------------------*/
      /* Check the next character by Unicode property. We will get here only
      if the support is in the binary; otherwise a compile-time error occurs.
      */

#ifdef SUPPORT_UCP
      case OP_PROP:
      case OP_NOTPROP:
      if (clen > 0)
        {
        BOOL OK;
        const ucd_record * prop = GET_UCD(c);
        switch(code[1])
          {
          case PT_ANY:
          OK = TRUE;
          break;

          case PT_LAMP:
          OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
               prop->chartype == ucp_Lt;
          break;

          case PT_GC:
          OK = PRIV(ucp_gentype)[prop->chartype] == code[2];
          break;

          case PT_PC:
          OK = prop->chartype == code[2];
          break;

          case PT_SC:
          OK = prop->script == code[2];
          break;

          /* These are specials for combination cases. */

          case PT_ALNUM:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N;
          break;

          case PT_SPACE:    /* Perl space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_PXSPACE:  /* POSIX space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
               c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_WORD:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
               c == CHAR_UNDERSCORE;
          break;

          /* Should never occur, but keep compilers from grumbling. */

          default:
          OK = codevalue != OP_PROP;
          break;
          }

        if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); }
        }
      break;
#endif



/* ========================================================================== */
      /* These opcodes likewise inspect the subject character, but have an
      argument that is not a data character. It is one of these opcodes:
      OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,
      OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */

      case OP_TYPEPLUS:
      case OP_TYPEMINPLUS:
      case OP_TYPEPOSPLUS:
      count = current_state->count;  /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
      if (clen > 0)
        {
        if (d == OP_ANY && ptr + 1 >= md->end_subject &&
            (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            c == NLBLOCK->nl[0])
          {
          could_continue = partial_newline = TRUE;
          }
        else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
            (c < 256 &&
              (d != OP_ANY || !IS_NEWLINE(ptr)) &&
              ((ctypes[c] & toptable1[d])  toptable2[d]) != 0))
          {
          if (count > 0 && codevalue == OP_TYPEPOSPLUS)
            {
            active_count--;            /* Remove non-match possibility */
            next_active_state--;
            }
          count++;
          ADD_NEW(state_offset, count);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_TYPEQUERY:
      case OP_TYPEMINQUERY:
      case OP_TYPEPOSQUERY:
      ADD_ACTIVE(state_offset + 2, 0);
      if (clen > 0)
        {
        if (d == OP_ANY && ptr + 1 >= md->end_subject &&
            (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            c == NLBLOCK->nl[0])
          {
          could_continue = partial_newline = TRUE;
          }
        else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
            (c < 256 &&
              (d != OP_ANY || !IS_NEWLINE(ptr)) &&
              ((ctypes[c] & toptable1[d])  toptable2[d]) != 0))
          {
          if (codevalue == OP_TYPEPOSQUERY)
            {
            active_count--;            /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW(state_offset + 2, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_TYPESTAR:
      case OP_TYPEMINSTAR:
      case OP_TYPEPOSSTAR:
      ADD_ACTIVE(state_offset + 2, 0);
      if (clen > 0)
        {
        if (d == OP_ANY && ptr + 1 >= md->end_subject &&
            (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            c == NLBLOCK->nl[0])
          {
          could_continue = partial_newline = TRUE;
          }
        else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
            (c < 256 &&
              (d != OP_ANY || !IS_NEWLINE(ptr)) &&
              ((ctypes[c] & toptable1[d])  toptable2[d]) != 0))
          {
          if (codevalue == OP_TYPEPOSSTAR)
            {
            active_count--;            /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW(state_offset, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_TYPEEXACT:
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        if (d == OP_ANY && ptr + 1 >= md->end_subject &&
            (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            c == NLBLOCK->nl[0])
          {
          could_continue = partial_newline = TRUE;
          }
        else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
            (c < 256 &&
              (d != OP_ANY || !IS_NEWLINE(ptr)) &&
              ((ctypes[c] & toptable1[d])  toptable2[d]) != 0))
          {
          if (++count >= GET2(code, 1))
            { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); }
          else
            { ADD_NEW(state_offset, count); }
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_TYPEUPTO:
      case OP_TYPEMINUPTO:
      case OP_TYPEPOSUPTO:
      ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0);
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        if (d == OP_ANY && ptr + 1 >= md->end_subject &&
            (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            c == NLBLOCK->nl[0])
          {
          could_continue = partial_newline = TRUE;
          }
        else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
            (c < 256 &&
              (d != OP_ANY || !IS_NEWLINE(ptr)) &&
              ((ctypes[c] & toptable1[d])  toptable2[d]) != 0))
          {
          if (codevalue == OP_TYPEPOSUPTO)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          if (++count >= GET2(code, 1))
            { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); }
          else
            { ADD_NEW(state_offset, count); }
          }
        }
      break;

/* ========================================================================== */
      /* These are virtual opcodes that are used when something like
      OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its
      argument. It keeps the code above fast for the other cases. The argument
      is in the d variable. */

#ifdef SUPPORT_UCP
      case OP_PROP_EXTRA + OP_TYPEPLUS:
      case OP_PROP_EXTRA + OP_TYPEMINPLUS:
      case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
      count = current_state->count;           /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }
      if (clen > 0)
        {
        BOOL OK;
        const ucd_record * prop = GET_UCD(c);
        switch(code[2])
          {
          case PT_ANY:
          OK = TRUE;
          break;

          case PT_LAMP:
          OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
            prop->chartype == ucp_Lt;
          break;

          case PT_GC:
          OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
          break;

          case PT_PC:
          OK = prop->chartype == code[3];
          break;

          case PT_SC:
          OK = prop->script == code[3];
          break;

          /* These are specials for combination cases. */

          case PT_ALNUM:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N;
          break;

          case PT_SPACE:    /* Perl space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_PXSPACE:  /* POSIX space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
               c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_WORD:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
               c == CHAR_UNDERSCORE;
          break;

          /* Should never occur, but keep compilers from grumbling. */

          default:
          OK = codevalue != OP_PROP;
          break;
          }

        if (OK == (d == OP_PROP))
          {
          if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          count++;
          ADD_NEW(state_offset, count);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_EXTUNI_EXTRA + OP_TYPEPLUS:
      case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:
      case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
      count = current_state->count;  /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
      if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
        {
        const pcre_uchar *nptr = ptr + clen;
        int ncount = 0;
        if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
          {
          active_count--;           /* Remove non-match possibility */
          next_active_state--;
          }
        while (nptr < end_subject)
          {
          int nd;
          int ndlen = 1;
          GETCHARLEN(nd, nptr, ndlen);
          if (UCD_CATEGORY(nd) != ucp_M) break;
          ncount++;
          nptr += ndlen;
          }
        count++;
        ADD_NEW_DATA(-state_offset, count, ncount);
        }
      break;
#endif

      /*-----------------------------------------------------------------*/
      case OP_ANYNL_EXTRA + OP_TYPEPLUS:
      case OP_ANYNL_EXTRA + OP_TYPEMINPLUS:
      case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS:
      count = current_state->count;  /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
      if (clen > 0)
        {
        int ncount = 0;
        switch (c)
          {
          case 0x000b:
          case 0x000c:
          case 0x0085:
          case 0x2028:
          case 0x2029:
          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
          goto ANYNL01;

          case 0x000d:
          if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
          /* Fall through */

          ANYNL01:
          case 0x000a:
          if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          count++;
          ADD_NEW_DATA(-state_offset, count, ncount);
          break;

          default:
          break;
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_VSPACE_EXTRA + OP_TYPEPLUS:
      case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:
      case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:
      count = current_state->count;  /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
      if (clen > 0)
        {
        BOOL OK;
        switch (c)
          {
          case 0x000a:
          case 0x000b:
          case 0x000c:
          case 0x000d:
          case 0x0085:
          case 0x2028:
          case 0x2029:
          OK = TRUE;
          break;

          default:
          OK = FALSE;
          break;
          }

        if (OK == (d == OP_VSPACE))
          {
          if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          count++;
          ADD_NEW_DATA(-state_offset, count, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_HSPACE_EXTRA + OP_TYPEPLUS:
      case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:
      case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:
      count = current_state->count;  /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
      if (clen > 0)
        {
        BOOL OK;
        switch (c)
          {
          case 0x09:      /* HT */
          case 0x20:      /* SPACE */
          case 0xa0:      /* NBSP */
          case 0x1680:    /* OGHAM SPACE MARK */
          case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
          case 0x2000:    /* EN QUAD */
          case 0x2001:    /* EM QUAD */
          case 0x2002:    /* EN SPACE */
          case 0x2003:    /* EM SPACE */
          case 0x2004:    /* THREE-PER-EM SPACE */
          case 0x2005:    /* FOUR-PER-EM SPACE */
          case 0x2006:    /* SIX-PER-EM SPACE */
          case 0x2007:    /* FIGURE SPACE */
          case 0x2008:    /* PUNCTUATION SPACE */
          case 0x2009:    /* THIN SPACE */
          case 0x200A:    /* HAIR SPACE */
          case 0x202f:    /* NARROW NO-BREAK SPACE */
          case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
          case 0x3000:    /* IDEOGRAPHIC SPACE */
          OK = TRUE;
          break;

          default:
          OK = FALSE;
          break;
          }

        if (OK == (d == OP_HSPACE))
          {
          if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          count++;
          ADD_NEW_DATA(-state_offset, count, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
#ifdef SUPPORT_UCP
      case OP_PROP_EXTRA + OP_TYPEQUERY:
      case OP_PROP_EXTRA + OP_TYPEMINQUERY:
      case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
      count = 4;
      goto QS1;

      case OP_PROP_EXTRA + OP_TYPESTAR:
      case OP_PROP_EXTRA + OP_TYPEMINSTAR:
      case OP_PROP_EXTRA + OP_TYPEPOSSTAR:
      count = 0;

      QS1:

      ADD_ACTIVE(state_offset + 4, 0);
      if (clen > 0)
        {
        BOOL OK;
        const ucd_record * prop = GET_UCD(c);
        switch(code[2])
          {
          case PT_ANY:
          OK = TRUE;
          break;

          case PT_LAMP:
          OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
            prop->chartype == ucp_Lt;
          break;

          case PT_GC:
          OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
          break;

          case PT_PC:
          OK = prop->chartype == code[3];
          break;

          case PT_SC:
          OK = prop->script == code[3];
          break;

          /* These are specials for combination cases. */

          case PT_ALNUM:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N;
          break;

          case PT_SPACE:    /* Perl space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_PXSPACE:  /* POSIX space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
               c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_WORD:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
               c == CHAR_UNDERSCORE;
          break;

          /* Should never occur, but keep compilers from grumbling. */

          default:
          OK = codevalue != OP_PROP;
          break;
          }

        if (OK == (d == OP_PROP))
          {
          if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR ||
              codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW(state_offset + count, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_EXTUNI_EXTRA + OP_TYPEQUERY:
      case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:
      case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY:
      count = 2;
      goto QS2;

      case OP_EXTUNI_EXTRA + OP_TYPESTAR:
      case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:
      case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR:
      count = 0;

      QS2:

      ADD_ACTIVE(state_offset + 2, 0);
      if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
        {
        const pcre_uchar *nptr = ptr + clen;
        int ncount = 0;
        if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
            codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
          {
          active_count--;           /* Remove non-match possibility */
          next_active_state--;
          }
        while (nptr < end_subject)
          {
          int nd;
          int ndlen = 1;
          GETCHARLEN(nd, nptr, ndlen);
          if (UCD_CATEGORY(nd) != ucp_M) break;
          ncount++;
          nptr += ndlen;
          }
        ADD_NEW_DATA(-(state_offset + count), 0, ncount);
        }
      break;
#endif

      /*-----------------------------------------------------------------*/
      case OP_ANYNL_EXTRA + OP_TYPEQUERY:
      case OP_ANYNL_EXTRA + OP_TYPEMINQUERY:
      case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY:
      count = 2;
      goto QS3;

      case OP_ANYNL_EXTRA + OP_TYPESTAR:
      case OP_ANYNL_EXTRA + OP_TYPEMINSTAR:
      case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR:
      count = 0;

      QS3:
      ADD_ACTIVE(state_offset + 2, 0);
      if (clen > 0)
        {
        int ncount = 0;
        switch (c)
          {
          case 0x000b:
          case 0x000c:
          case 0x0085:
          case 0x2028:
          case 0x2029:
          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
          goto ANYNL02;

          case 0x000d:
          if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
          /* Fall through */

          ANYNL02:
          case 0x000a:
          if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
              codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW_DATA(-(state_offset + count), 0, ncount);
          break;

          default:
          break;
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_VSPACE_EXTRA + OP_TYPEQUERY:
      case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:
      case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:
      count = 2;
      goto QS4;

      case OP_VSPACE_EXTRA + OP_TYPESTAR:
      case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:
      case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:
      count = 0;

      QS4:
      ADD_ACTIVE(state_offset + 2, 0);
      if (clen > 0)
        {
        BOOL OK;
        switch (c)
          {
          case 0x000a:
          case 0x000b:
          case 0x000c:
          case 0x000d:
          case 0x0085:
          case 0x2028:
          case 0x2029:
          OK = TRUE;
          break;

          default:
          OK = FALSE;
          break;
          }
        if (OK == (d == OP_VSPACE))
          {
          if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||
              codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW_DATA(-(state_offset + count), 0, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_HSPACE_EXTRA + OP_TYPEQUERY:
      case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:
      case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:
      count = 2;
      goto QS5;

      case OP_HSPACE_EXTRA + OP_TYPESTAR:
      case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:
      case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:
      count = 0;

      QS5:
      ADD_ACTIVE(state_offset + 2, 0);
      if (clen > 0)
        {
        BOOL OK;
        switch (c)
          {
          case 0x09:      /* HT */
          case 0x20:      /* SPACE */
          case 0xa0:      /* NBSP */
          case 0x1680:    /* OGHAM SPACE MARK */
          case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
          case 0x2000:    /* EN QUAD */
          case 0x2001:    /* EM QUAD */
          case 0x2002:    /* EN SPACE */
          case 0x2003:    /* EM SPACE */
          case 0x2004:    /* THREE-PER-EM SPACE */
          case 0x2005:    /* FOUR-PER-EM SPACE */
          case 0x2006:    /* SIX-PER-EM SPACE */
          case 0x2007:    /* FIGURE SPACE */
          case 0x2008:    /* PUNCTUATION SPACE */
          case 0x2009:    /* THIN SPACE */
          case 0x200A:    /* HAIR SPACE */
          case 0x202f:    /* NARROW NO-BREAK SPACE */
          case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
          case 0x3000:    /* IDEOGRAPHIC SPACE */
          OK = TRUE;
          break;

          default:
          OK = FALSE;
          break;
          }

        if (OK == (d == OP_HSPACE))
          {
          if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||
              codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW_DATA(-(state_offset + count), 0, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
#ifdef SUPPORT_UCP
      case OP_PROP_EXTRA + OP_TYPEEXACT:
      case OP_PROP_EXTRA + OP_TYPEUPTO:
      case OP_PROP_EXTRA + OP_TYPEMINUPTO:
      case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
      if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
        { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); }
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        BOOL OK;
        const ucd_record * prop = GET_UCD(c);
        switch(code[1 + IMM2_SIZE + 1])
          {
          case PT_ANY:
          OK = TRUE;
          break;

          case PT_LAMP:
          OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
            prop->chartype == ucp_Lt;
          break;

          case PT_GC:
          OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2];
          break;

          case PT_PC:
          OK = prop->chartype == code[1 + IMM2_SIZE + 2];
          break;

          case PT_SC:
          OK = prop->script == code[1 + IMM2_SIZE + 2];
          break;

          /* These are specials for combination cases. */

          case PT_ALNUM:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N;
          break;

          case PT_SPACE:    /* Perl space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_PXSPACE:  /* POSIX space */
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
               c == CHAR_FF || c == CHAR_CR;
          break;

          case PT_WORD:
          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
               c == CHAR_UNDERSCORE;
          break;

          /* Should never occur, but keep compilers from grumbling. */

          default:
          OK = codevalue != OP_PROP;
          break;
          }

        if (OK == (d == OP_PROP))
          {
          if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          if (++count >= GET2(code, 1))
            { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); }
          else
            { ADD_NEW(state_offset, count); }
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_EXTUNI_EXTRA + OP_TYPEEXACT:
      case OP_EXTUNI_EXTRA + OP_TYPEUPTO:
      case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
      case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
      if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
        { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
      count = current_state->count;  /* Number already matched */
      if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
        {
        const pcre_uchar *nptr = ptr + clen;
        int ncount = 0;
        if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
          {
          active_count--;           /* Remove non-match possibility */
          next_active_state--;
          }
        while (nptr < end_subject)
          {
          int nd;
          int ndlen = 1;
          GETCHARLEN(nd, nptr, ndlen);
          if (UCD_CATEGORY(nd) != ucp_M) break;
          ncount++;
          nptr += ndlen;
          }
        if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
            reset_could_continue = TRUE;
        if (++count >= GET2(code, 1))
          { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
        else
          { ADD_NEW_DATA(-state_offset, count, ncount); }
        }
      break;
#endif

      /*-----------------------------------------------------------------*/
      case OP_ANYNL_EXTRA + OP_TYPEEXACT:
      case OP_ANYNL_EXTRA + OP_TYPEUPTO:
      case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
      case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
      if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
        { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        int ncount = 0;
        switch (c)
          {
          case 0x000b:
          case 0x000c:
          case 0x0085:
          case 0x2028:
          case 0x2029:
          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
          goto ANYNL03;

          case 0x000d:
          if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
          /* Fall through */

          ANYNL03:
          case 0x000a:
          if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          if (++count >= GET2(code, 1))
            { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
          else
            { ADD_NEW_DATA(-state_offset, count, ncount); }
          break;

          default:
          break;
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_VSPACE_EXTRA + OP_TYPEEXACT:
      case OP_VSPACE_EXTRA + OP_TYPEUPTO:
      case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
      case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
      if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
        { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        BOOL OK;
        switch (c)
          {
          case 0x000a:
          case 0x000b:
          case 0x000c:
          case 0x000d:
          case 0x0085:
          case 0x2028:
          case 0x2029:
          OK = TRUE;
          break;

          default:
          OK = FALSE;
          }

        if (OK == (d == OP_VSPACE))
          {
          if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          if (++count >= GET2(code, 1))
            { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
          else
            { ADD_NEW_DATA(-state_offset, count, 0); }
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_HSPACE_EXTRA + OP_TYPEEXACT:
      case OP_HSPACE_EXTRA + OP_TYPEUPTO:
      case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
      case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
      if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
        { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        BOOL OK;
        switch (c)
          {
          case 0x09:      /* HT */
          case 0x20:      /* SPACE */
          case 0xa0:      /* NBSP */
          case 0x1680:    /* OGHAM SPACE MARK */
          case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
          case 0x2000:    /* EN QUAD */
          case 0x2001:    /* EM QUAD */
          case 0x2002:    /* EN SPACE */
          case 0x2003:    /* EM SPACE */
          case 0x2004:    /* THREE-PER-EM SPACE */
          case 0x2005:    /* FOUR-PER-EM SPACE */
          case 0x2006:    /* SIX-PER-EM SPACE */
          case 0x2007:    /* FIGURE SPACE */
          case 0x2008:    /* PUNCTUATION SPACE */
          case 0x2009:    /* THIN SPACE */
          case 0x200A:    /* HAIR SPACE */
          case 0x202f:    /* NARROW NO-BREAK SPACE */
          case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
          case 0x3000:    /* IDEOGRAPHIC SPACE */
          OK = TRUE;
          break;

          default:
          OK = FALSE;
          break;
          }

        if (OK == (d == OP_HSPACE))
          {
          if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)
            {
            active_count--;           /* Remove non-match possibility */
            next_active_state--;
            }
          if (++count >= GET2(code, 1))
            { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
          else
            { ADD_NEW_DATA(-state_offset, count, 0); }
          }
        }
      break;

/* ========================================================================== */
      /* These opcodes are followed by a character that is usually compared
      to the current subject character; it is loaded into d. We still get
      here even if there is no subject character, because in some cases zero
      repetitions are permitted. */

      /*-----------------------------------------------------------------*/
      case OP_CHAR:
      if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      case OP_CHARI:
      if (clen == 0) break;

#ifdef SUPPORT_UTF
      if (utf)
        {
        if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
          {
          unsigned int othercase;
          if (c < 128)
            othercase = fcc[c];
          else
            /* If we have Unicode property support, we can use it to test the
            other case of the character. */
#ifdef SUPPORT_UCP
            othercase = UCD_OTHERCASE(c);
#else
            othercase = NOTACHAR;
#endif

          if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
          }
        }
      else
#endif  /* SUPPORT_UTF */
      /* Not UTF mode */
        {
        if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
          { ADD_NEW(state_offset + 2, 0); }
        }
      break;


#ifdef SUPPORT_UCP
      /*-----------------------------------------------------------------*/
      /* This is a tricky one because it can match more than one character.
      Find out how many characters to skip, and then set up a negative state
      to wait for them to pass before continuing. */

      case OP_EXTUNI:
      if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
        {
        const pcre_uchar *nptr = ptr + clen;
        int ncount = 0;
        while (nptr < end_subject)
          {
          int nclen = 1;
          GETCHARLEN(c, nptr, nclen);
          if (UCD_CATEGORY(c) != ucp_M) break;
          ncount++;
          nptr += nclen;
          }
        if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
            reset_could_continue = TRUE;
        ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
        }
      break;
#endif

      /*-----------------------------------------------------------------*/
      /* This is a tricky like EXTUNI because it too can match more than one
      character (when CR is followed by LF). In this case, set up a negative
      state to wait for one character to pass before continuing. */

      case OP_ANYNL:
      if (clen > 0) switch(c)
        {
        case 0x000b:
        case 0x000c:
        case 0x0085:
        case 0x2028:
        case 0x2029:
        if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;

        case 0x000a:
        ADD_NEW(state_offset + 1, 0);
        break;

        case 0x000d:
        if (ptr + 1 >= end_subject)
          {
          ADD_NEW(state_offset + 1, 0);
          if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
            reset_could_continue = TRUE;
          }
        else if (ptr[1] == 0x0a)
          {
          ADD_NEW_DATA(-(state_offset + 1), 0, 1);
          }
        else
          {
          ADD_NEW(state_offset + 1, 0);
          }
        break;
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_NOT_VSPACE:
      if (clen > 0) switch(c)
        {
        case 0x000a:
        case 0x000b:
        case 0x000c:
        case 0x000d:
        case 0x0085:
        case 0x2028:
        case 0x2029:
        break;

        default:
        ADD_NEW(state_offset + 1, 0);
        break;
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_VSPACE:
      if (clen > 0) switch(c)
        {
        case 0x000a:
        case 0x000b:
        case 0x000c:
        case 0x000d:
        case 0x0085:
        case 0x2028:
        case 0x2029:
        ADD_NEW(state_offset + 1, 0);
        break;

        default: break;
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_NOT_HSPACE:
      if (clen > 0) switch(c)
        {
        case 0x09:      /* HT */
        case 0x20:      /* SPACE */
        case 0xa0:      /* NBSP */
        case 0x1680:    /* OGHAM SPACE MARK */
        case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
        case 0x2000:    /* EN QUAD */
        case 0x2001:    /* EM QUAD */
        case 0x2002:    /* EN SPACE */
        case 0x2003:    /* EM SPACE */
        case 0x2004:    /* THREE-PER-EM SPACE */
        case 0x2005:    /* FOUR-PER-EM SPACE */
        case 0x2006:    /* SIX-PER-EM SPACE */
        case 0x2007:    /* FIGURE SPACE */
        case 0x2008:    /* PUNCTUATION SPACE */
        case 0x2009:    /* THIN SPACE */
        case 0x200A:    /* HAIR SPACE */
        case 0x202f:    /* NARROW NO-BREAK SPACE */
        case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
        case 0x3000:    /* IDEOGRAPHIC SPACE */
        break;

        default:
        ADD_NEW(state_offset + 1, 0);
        break;
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_HSPACE:
      if (clen > 0) switch(c)
        {
        case 0x09:      /* HT */
        case 0x20:      /* SPACE */
        case 0xa0:      /* NBSP */
        case 0x1680:    /* OGHAM SPACE MARK */
        case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
        case 0x2000:    /* EN QUAD */
        case 0x2001:    /* EM QUAD */
        case 0x2002:    /* EN SPACE */
        case 0x2003:    /* EM SPACE */
        case 0x2004:    /* THREE-PER-EM SPACE */
        case 0x2005:    /* FOUR-PER-EM SPACE */
        case 0x2006:    /* SIX-PER-EM SPACE */
        case 0x2007:    /* FIGURE SPACE */
        case 0x2008:    /* PUNCTUATION SPACE */
        case 0x2009:    /* THIN SPACE */
        case 0x200A:    /* HAIR SPACE */
        case 0x202f:    /* NARROW NO-BREAK SPACE */
        case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
        case 0x3000:    /* IDEOGRAPHIC SPACE */
        ADD_NEW(state_offset + 1, 0);
        break;
        }
      break;

      /*-----------------------------------------------------------------*/
      /* Match a negated single character casefully. */

      case OP_NOT:
      if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
      break;

      /*-----------------------------------------------------------------*/
      /* Match a negated single character caselessly. */

      case OP_NOTI:
      if (clen > 0)
        {
        unsigned int otherd;
#ifdef SUPPORT_UTF
        if (utf && d >= 128)
          {
#ifdef SUPPORT_UCP
          otherd = UCD_OTHERCASE(d);
#endif  /* SUPPORT_UCP */
          }
        else
#endif  /* SUPPORT_UTF */
        otherd = TABLE_GET(d, fcc, d);
        if (c != d && c != otherd)
          { ADD_NEW(state_offset + dlen + 1, 0); }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_PLUSI:
      case OP_MINPLUSI:
      case OP_POSPLUSI:
      case OP_NOTPLUSI:
      case OP_NOTMINPLUSI:
      case OP_NOTPOSPLUSI:
      caseless = TRUE;
      codevalue -= OP_STARI - OP_STAR;

      /* Fall through */
      case OP_PLUS:
      case OP_MINPLUS:
      case OP_POSPLUS:
      case OP_NOTPLUS:
      case OP_NOTMINPLUS:
      case OP_NOTPOSPLUS:
      count = current_state->count;  /* Already matched */
      if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
      if (clen > 0)
        {
        unsigned int otherd = NOTACHAR;
        if (caseless)
          {
#ifdef SUPPORT_UTF
          if (utf && d >= 128)
            {
#ifdef SUPPORT_UCP
            otherd = UCD_OTHERCASE(d);
#endif  /* SUPPORT_UCP */
            }
          else
#endif  /* SUPPORT_UTF */
          otherd = TABLE_GET(d, fcc, d);
          }
        if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
          {
          if (count > 0 &&
              (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS))
            {
            active_count--;             /* Remove non-match possibility */
            next_active_state--;
            }
          count++;
          ADD_NEW(state_offset, count);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_QUERYI:
      case OP_MINQUERYI:
      case OP_POSQUERYI:
      case OP_NOTQUERYI:
      case OP_NOTMINQUERYI:
      case OP_NOTPOSQUERYI:
      caseless = TRUE;
      codevalue -= OP_STARI - OP_STAR;
      /* Fall through */
      case OP_QUERY:
      case OP_MINQUERY:
      case OP_POSQUERY:
      case OP_NOTQUERY:
      case OP_NOTMINQUERY:
      case OP_NOTPOSQUERY:
      ADD_ACTIVE(state_offset + dlen + 1, 0);
      if (clen > 0)
        {
        unsigned int otherd = NOTACHAR;
        if (caseless)
          {
#ifdef SUPPORT_UTF
          if (utf && d >= 128)
            {
#ifdef SUPPORT_UCP
            otherd = UCD_OTHERCASE(d);
#endif  /* SUPPORT_UCP */
            }
          else
#endif  /* SUPPORT_UTF */
          otherd = TABLE_GET(d, fcc, d);
          }
        if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
          {
          if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY)
            {
            active_count--;            /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW(state_offset + dlen + 1, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_STARI:
      case OP_MINSTARI:
      case OP_POSSTARI:
      case OP_NOTSTARI:
      case OP_NOTMINSTARI:
      case OP_NOTPOSSTARI:
      caseless = TRUE;
      codevalue -= OP_STARI - OP_STAR;
      /* Fall through */
      case OP_STAR:
      case OP_MINSTAR:
      case OP_POSSTAR:
      case OP_NOTSTAR:
      case OP_NOTMINSTAR:
      case OP_NOTPOSSTAR:
      ADD_ACTIVE(state_offset + dlen + 1, 0);
      if (clen > 0)
        {
        unsigned int otherd = NOTACHAR;
        if (caseless)
          {
#ifdef SUPPORT_UTF
          if (utf && d >= 128)
            {
#ifdef SUPPORT_UCP
            otherd = UCD_OTHERCASE(d);
#endif  /* SUPPORT_UCP */
            }
          else
#endif  /* SUPPORT_UTF */
          otherd = TABLE_GET(d, fcc, d);
          }
        if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
          {
          if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR)
            {
            active_count--;            /* Remove non-match possibility */
            next_active_state--;
            }
          ADD_NEW(state_offset, 0);
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_EXACTI:
      case OP_NOTEXACTI:
      caseless = TRUE;
      codevalue -= OP_STARI - OP_STAR;
      /* Fall through */
      case OP_EXACT:
      case OP_NOTEXACT:
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        unsigned int otherd = NOTACHAR;
        if (caseless)
          {
#ifdef SUPPORT_UTF
          if (utf && d >= 128)
            {
#ifdef SUPPORT_UCP
            otherd = UCD_OTHERCASE(d);
#endif  /* SUPPORT_UCP */
            }
          else
#endif  /* SUPPORT_UTF */
          otherd = TABLE_GET(d, fcc, d);
          }
        if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
          {
          if (++count >= GET2(code, 1))
            { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
          else
            { ADD_NEW(state_offset, count); }
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_UPTOI:
      case OP_MINUPTOI:
      case OP_POSUPTOI:
      case OP_NOTUPTOI:
      case OP_NOTMINUPTOI:
      case OP_NOTPOSUPTOI:
      caseless = TRUE;
      codevalue -= OP_STARI - OP_STAR;
      /* Fall through */
      case OP_UPTO:
      case OP_MINUPTO:
      case OP_POSUPTO:
      case OP_NOTUPTO:
      case OP_NOTMINUPTO:
      case OP_NOTPOSUPTO:
      ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0);
      count = current_state->count;  /* Number already matched */
      if (clen > 0)
        {
        unsigned int otherd = NOTACHAR;
        if (caseless)
          {
#ifdef SUPPORT_UTF
          if (utf && d >= 128)
            {
#ifdef SUPPORT_UCP
            otherd = UCD_OTHERCASE(d);
#endif  /* SUPPORT_UCP */
            }
          else
#endif  /* SUPPORT_UTF */
          otherd = TABLE_GET(d, fcc, d);
          }
        if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
          {
          if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO)
            {
            active_count--;             /* Remove non-match possibility */
            next_active_state--;
            }
          if (++count >= GET2(code, 1))
            { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
          else
            { ADD_NEW(state_offset, count); }
          }
        }
      break;


/* ========================================================================== */
      /* These are the class-handling opcodes */

      case OP_CLASS:
      case OP_NCLASS:
      case OP_XCLASS:
        {
        BOOL isinclass = FALSE;
        int next_state_offset;
        const pcre_uchar *ecode;

        /* For a simple class, there is always just a 32-byte table, and we
        can set isinclass from it. */

        if (codevalue != OP_XCLASS)
          {
          ecode = code + 1 + (32 / sizeof(pcre_uchar));
          if (clen > 0)
            {
            isinclass = (c > 255)? (codevalue == OP_NCLASS) :
              ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0);
            }
          }

        /* An extended class may have a table or a list of single characters,
        ranges, or both, and it may be positive or negative. There's a
        function that sorts all this out. */

        else
         {
         ecode = code + GET(code, 1);
         if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);
         }

        /* At this point, isinclass is set for all kinds of class, and ecode
        points to the byte after the end of the class. If there is a
        quantifier, this is where it will be. */

        next_state_offset = (int)(ecode - start_code);

        switch (*ecode)
          {
          case OP_CRSTAR:
          case OP_CRMINSTAR:
          ADD_ACTIVE(next_state_offset + 1, 0);
          if (isinclass) { ADD_NEW(state_offset, 0); }
          break;

          case OP_CRPLUS:
          case OP_CRMINPLUS:
          count = current_state->count;  /* Already matched */
          if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); }
          if (isinclass) { count++; ADD_NEW(state_offset, count); }
          break;

          case OP_CRQUERY:
          case OP_CRMINQUERY:
          ADD_ACTIVE(next_state_offset + 1, 0);
          if (isinclass) { ADD_NEW(next_state_offset + 1, 0); }
          break;

          case OP_CRRANGE:
          case OP_CRMINRANGE:
          count = current_state->count;  /* Already matched */
          if (count >= GET2(ecode, 1))
            { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
          if (isinclass)
            {
            int max = GET2(ecode, 1 + IMM2_SIZE);
            if (++count >= max && max != 0)   /* Max 0 => no limit */
              { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
            else
              { ADD_NEW(state_offset, count); }
            }
          break;

          default:
          if (isinclass) { ADD_NEW(next_state_offset, 0); }
          break;
          }
        }
      break;

/* ========================================================================== */
      /* These are the opcodes for fancy brackets of various kinds. We have
      to use recursion in order to handle them. The "always failing" assertion
      (?!) is optimised to OP_FAIL when compiling, so we have to support that,
      though the other "backtracking verbs" are not supported. */

      case OP_FAIL:
      forced_fail++;    /* Count FAILs for multiple states */
      break;

      case OP_ASSERT:
      case OP_ASSERT_NOT:
      case OP_ASSERTBACK:
      case OP_ASSERTBACK_NOT:
        {
        int rc;
        int local_offsets[2];
        int local_workspace[1000];
        const pcre_uchar *endasscode = code + GET(code, 1);

        while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);

        rc = internal_dfa_exec(
          md,                                   /* static match data */
          code,                                 /* this subexpression's code */
          ptr,                                  /* where we currently are */
          (int)(ptr - start_subject),           /* start offset */
          local_offsets,                        /* offset vector */
          sizeof(local_offsets)/sizeof(int),    /* size of same */
          local_workspace,                      /* workspace vector */
          sizeof(local_workspace)/sizeof(int),  /* size of same */
          rlevel);                              /* function recursion level */

        if (rc == PCRE_ERROR_DFA_UITEM) return rc;
        if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
            { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_COND:
      case OP_SCOND:
        {
        int local_offsets[1000];
        int local_workspace[1000];
        int codelink = GET(code, 1);
        int condcode;

        /* Because of the way auto-callout works during compile, a callout item
        is inserted between OP_COND and an assertion condition. This does not
        happen for the other conditions. */

        if (code[LINK_SIZE+1] == OP_CALLOUT)
          {
          rrc = 0;
          if (PUBL(callout) != NULL)
            {
            PUBL(callout_block) cb;
            cb.version          = 1;   /* Version 1 of the callout block */
            cb.callout_number   = code[LINK_SIZE+2];
            cb.offset_vector    = offsets;
#ifdef COMPILE_PCRE8
            cb.subject          = (PCRE_SPTR)start_subject;
#else
            cb.subject          = (PCRE_SPTR16)start_subject;
#endif
            cb.subject_length   = (int)(end_subject - start_subject);
            cb.start_match      = (int)(current_subject - start_subject);
            cb.current_position = (int)(ptr - start_subject);
            cb.pattern_position = GET(code, LINK_SIZE + 3);
            cb.next_item_length = GET(code, 3 + 2*LINK_SIZE);
            cb.capture_top      = 1;
            cb.capture_last     = -1;
            cb.callout_data     = md->callout_data;
            cb.mark             = NULL;   /* No (*MARK) support */
            if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
            }
          if (rrc > 0) break;                      /* Fail this thread */
          code += PRIV(OP_lengths)[OP_CALLOUT];    /* Skip callout data */
          }

        condcode = code[LINK_SIZE+1];

        /* Back reference conditions are not supported */

        if (condcode == OP_CREF || condcode == OP_NCREF)
          return PCRE_ERROR_DFA_UCOND;

        /* The DEFINE condition is always false */

        if (condcode == OP_DEF)
          { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }

        /* The only supported version of OP_RREF is for the value RREF_ANY,
        which means "test if in any recursion". We can't test for specifically
        recursed groups. */

        else if (condcode == OP_RREF || condcode == OP_NRREF)
          {
          int value = GET2(code, LINK_SIZE + 2);
          if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
          if (md->recursive != NULL)
            { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); }
          else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
          }

        /* Otherwise, the condition is an assertion */

        else
          {
          int rc;
          const pcre_uchar *asscode = code + LINK_SIZE + 1;
          const pcre_uchar *endasscode = asscode + GET(asscode, 1);

          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);

          rc = internal_dfa_exec(
            md,                                   /* fixed match data */
            asscode,                              /* this subexpression's code */
            ptr,                                  /* where we currently are */
            (int)(ptr - start_subject),           /* start offset */
            local_offsets,                        /* offset vector */
            sizeof(local_offsets)/sizeof(int),    /* size of same */
            local_workspace,                      /* workspace vector */
            sizeof(local_workspace)/sizeof(int),  /* size of same */
            rlevel);                              /* function recursion level */

          if (rc == PCRE_ERROR_DFA_UITEM) return rc;
          if ((rc >= 0) ==
                (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
            { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
          else
            { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_RECURSE:
        {
        dfa_recursion_info *ri;
        int local_offsets[1000];
        int local_workspace[1000];
        const pcre_uchar *callpat = start_code + GET(code, 1);
        int recno = (callpat == md->start_code)? 0 :
          GET2(callpat, 1 + LINK_SIZE);
        int rc;

        DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP));

        /* Check for repeating a recursion without advancing the subject
        pointer. This should catch convoluted mutual recursions. (Some simple
        cases are caught at compile time.) */

        for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
          if (recno == ri->group_num && ptr == ri->subject_position)
            return PCRE_ERROR_RECURSELOOP;

        /* Remember this recursion and where we started it so as to
        catch infinite loops. */

        new_recursive.group_num = recno;
        new_recursive.subject_position = ptr;
        new_recursive.prevrec = md->recursive;
        md->recursive = &new_recursive;

        rc = internal_dfa_exec(
          md,                                   /* fixed match data */
          callpat,                              /* this subexpression's code */
          ptr,                                  /* where we currently are */
          (int)(ptr - start_subject),           /* start offset */
          local_offsets,                        /* offset vector */
          sizeof(local_offsets)/sizeof(int),    /* size of same */
          local_workspace,                      /* workspace vector */
          sizeof(local_workspace)/sizeof(int),  /* size of same */
          rlevel);                              /* function recursion level */

        md->recursive = new_recursive.prevrec;  /* Done this recursion */

        DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP,
          rc));

        /* Ran out of internal offsets */

        if (rc == 0) return PCRE_ERROR_DFA_RECURSE;

        /* For each successful matched substring, set up the next state with a
        count of characters to skip before trying it. Note that the count is in
        characters, not bytes. */

        if (rc > 0)
          {
          for (rc = rc*2 - 2; rc >= 0; rc -= 2)
            {
            int charcount = local_offsets[rc+1] - local_offsets[rc];
#ifdef SUPPORT_UTF
            if (utf)
              {
              const pcre_uchar *p = start_subject + local_offsets[rc];
              const pcre_uchar *pp = start_subject + local_offsets[rc+1];
              while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
              }
#endif
            if (charcount > 0)
              {
              ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));
              }
            else
              {
              ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0);
              }
            }
          }
        else if (rc != PCRE_ERROR_NOMATCH) return rc;
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_BRAPOS:
      case OP_SBRAPOS:
      case OP_CBRAPOS:
      case OP_SCBRAPOS:
      case OP_BRAPOSZERO:
        {
        int charcount, matched_count;
        const pcre_uchar *local_ptr = ptr;
        BOOL allow_zero;

        if (codevalue == OP_BRAPOSZERO)
          {
          allow_zero = TRUE;
          codevalue = *(++code);  /* Codevalue will be one of above BRAs */
          }
        else allow_zero = FALSE;

        /* Loop to match the subpattern as many times as possible as if it were
        a complete pattern. */

        for (matched_count = 0;; matched_count++)
          {
          int local_offsets[2];
          int local_workspace[1000];

          int rc = internal_dfa_exec(
            md,                                   /* fixed match data */
            code,                                 /* this subexpression's code */
            local_ptr,                            /* where we currently are */
            (int)(ptr - start_subject),           /* start offset */
            local_offsets,                        /* offset vector */
            sizeof(local_offsets)/sizeof(int),    /* size of same */
            local_workspace,                      /* workspace vector */
            sizeof(local_workspace)/sizeof(int),  /* size of same */
            rlevel);                              /* function recursion level */

          /* Failed to match */

          if (rc < 0)
            {
            if (rc != PCRE_ERROR_NOMATCH) return rc;
            break;
            }

          /* Matched: break the loop if zero characters matched. */

          charcount = local_offsets[1] - local_offsets[0];
          if (charcount == 0) break;
          local_ptr += charcount;    /* Advance temporary position ptr */
          }

        /* At this point we have matched the subpattern matched_count
        times, and local_ptr is pointing to the character after the end of the
        last match. */

        if (matched_count > 0 || allow_zero)
          {
          const pcre_uchar *end_subpattern = code;
          int next_state_offset;

          do { end_subpattern += GET(end_subpattern, 1); }
            while (*end_subpattern == OP_ALT);
          next_state_offset =
            (int)(end_subpattern - start_code + LINK_SIZE + 1);

          /* Optimization: if there are no more active states, and there
          are no new states yet set up, then skip over the subject string
          right here, to save looping. Otherwise, set up the new state to swing
          into action when the end of the matched substring is reached. */

          if (i + 1 >= active_count && new_count == 0)
            {
            ptr = local_ptr;
            clen = 0;
            ADD_NEW(next_state_offset, 0);
            }
          else
            {
            const pcre_uchar *p = ptr;
            const pcre_uchar *pp = local_ptr;
            charcount = (int)(pp - p);
#ifdef SUPPORT_UTF
            if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
#endif
            ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
            }
          }
        }
      break;

      /*-----------------------------------------------------------------*/
      case OP_ONCE:
      case OP_ONCE_NC:
        {
        int local_offsets[2];
        int local_workspace[1000];

        int rc = internal_dfa_exec(
          md,                                   /* fixed match data */
          code,                                 /* this subexpression's code */
          ptr,                                  /* where we currently are */
          (int)(ptr - start_subject),           /* start offset */
          local_offsets,                        /* offset vector */
          sizeof(local_offsets)/sizeof(int),    /* size of same */
          local_workspace,                      /* workspace vector */
          sizeof(local_workspace)/sizeof(int),  /* size of same */
          rlevel);                              /* function recursion level */

        if (rc >= 0)
          {
          const pcre_uchar *end_subpattern = code;
          int charcount = local_offsets[1] - local_offsets[0];
          int next_state_offset, repeat_state_offset;

          do { end_subpattern += GET(end_subpattern, 1); }
            while (*end_subpattern == OP_ALT);
          next_state_offset =
            (int)(end_subpattern - start_code + LINK_SIZE + 1);

          /* If the end of this subpattern is KETRMAX or KETRMIN, we must
          arrange for the repeat state also to be added to the relevant list.
          Calculate the offset, or set -1 for no repeat. */

          repeat_state_offset = (*end_subpattern == OP_KETRMAX ||
                                 *end_subpattern == OP_KETRMIN)?
            (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1;

          /* If we have matched an empty string, add the next state at the
          current character pointer. This is important so that the duplicate
          checking kicks in, which is what breaks infinite loops that match an
          empty string. */

          if (charcount == 0)
            {
            ADD_ACTIVE(next_state_offset, 0);
            }

          /* Optimization: if there are no more active states, and there
          are no new states yet set up, then skip over the subject string
          right here, to save looping. Otherwise, set up the new state to swing
          into action when the end of the matched substring is reached. */

          else if (i + 1 >= active_count && new_count == 0)
            {
            ptr += charcount;
            clen = 0;
            ADD_NEW(next_state_offset, 0);

            /* If we are adding a repeat state at the new character position,
            we must fudge things so that it is the only current state.
            Otherwise, it might be a duplicate of one we processed before, and
            that would cause it to be skipped. */

            if (repeat_state_offset >= 0)
              {
              next_active_state = active_states;
              active_count = 0;
              i = -1;
              ADD_ACTIVE(repeat_state_offset, 0);
              }
            }
          else
            {
#ifdef SUPPORT_UTF
            if (utf)
              {
              const pcre_uchar *p = start_subject + local_offsets[0];
              const pcre_uchar *pp = start_subject + local_offsets[1];
              while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
              }
#endif
            ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
            if (repeat_state_offset >= 0)
              { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
            }
          }
        else if (rc != PCRE_ERROR_NOMATCH) return rc;
        }
      break;


/* ========================================================================== */
      /* Handle callouts */

      case OP_CALLOUT:
      rrc = 0;
      if (PUBL(callout) != NULL)
        {
        PUBL(callout_block) cb;
        cb.version          = 1;   /* Version 1 of the callout block */
        cb.callout_number   = code[1];
        cb.offset_vector    = offsets;
#ifdef COMPILE_PCRE8
        cb.subject          = (PCRE_SPTR)start_subject;
#else
        cb.subject          = (PCRE_SPTR16)start_subject;
#endif
        cb.subject_length   = (int)(end_subject - start_subject);
        cb.start_match      = (int)(current_subject - start_subject);
        cb.current_position = (int)(ptr - start_subject);
        cb.pattern_position = GET(code, 2);
        cb.next_item_length = GET(code, 2 + LINK_SIZE);
        cb.capture_top      = 1;
        cb.capture_last     = -1;
        cb.callout_data     = md->callout_data;
        cb.mark             = NULL;   /* No (*MARK) support */
        if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
        }
      if (rrc == 0)
        { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); }
      break;


/* ========================================================================== */
      default:        /* Unsupported opcode */
      return PCRE_ERROR_DFA_UITEM;
      }

    NEXT_ACTIVE_STATE: continue;

    }      /* End of loop scanning active states */

  /* We have finished the processing at the current subject character. If no
  new states have been set for the next character, we have found all the
  matches that we are going to find. If we are at the top level and partial
  matching has been requested, check for appropriate conditions.

  The "forced_ fail" variable counts the number of (*F) encountered for the
  character. If it is equal to the original active_count (saved in
  workspace[1]) it means that (*F) was found on every active state. In this
  case we don't want to give a partial match.

  The "could_continue" variable is true if a state could have continued but
  for the fact that the end of the subject was reached. */

  if (new_count <= 0)
    {
    if (rlevel == 1 &&                               /* Top level, and */
        could_continue &&                            /* Some could go on, and */
        forced_fail != workspace[1] &&               /* Not all forced fail & */
        (                                            /* either... */
        (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
        ||                                           /* or... */
        ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
         match_count < 0)                            /* no matches */
        ) &&                                         /* And... */
        (
        partial_newline ||                           /* Either partial NL */
          (                                          /* or ... */
          ptr >= end_subject &&                /* End of subject and */
          ptr > md->start_used_ptr)            /* Inspected non-empty string */
          )
        )
      {
      if (offsetcount >= 2)
        {
        offsets[0] = (int)(md->start_used_ptr - start_subject);
        offsets[1] = (int)(end_subject - start_subject);
        }
      match_count = PCRE_ERROR_PARTIAL;
      }

    DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
      "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count,
      rlevel*2-2, SP));
    break;        /* In effect, "return", but see the comment below */
    }

  /* One or more states are active for the next character. */

  ptr += clen;    /* Advance to next subject character */
  }               /* Loop to move along the subject string */

/* Control gets here from "break" a few lines above. We do it this way because
if we use "return" above, we have compiler trouble. Some compilers warn if
there's nothing here because they think the function doesn't return a value. On
the other hand, if we put a dummy statement here, some more clever compilers
complain that it can't be reached. Sigh. */

return match_count;
}




/*************************************************
*    Execute a Regular Expression - DFA engine   *
*************************************************/

/* This external function applies a compiled re to a subject string using a DFA
engine. This function calls the internal function multiple times if the pattern
is not anchored.

Arguments:
  argument_re     points to the compiled expression
  extra_data      points to extra data or is NULL
  subject         points to the subject string
  length          length of subject string (may contain binary zeros)
  start_offset    where to start in the subject string
  options         option bits
  offsets         vector of match offsets
  offsetcount     size of same
  workspace       workspace vector
  wscount         size of same

Returns:          > 0 => number of match offset pairs placed in offsets
                  = 0 => offsets overflowed; longest matches are present
                   -1 => failed to match
                 < -1 => some kind of unexpected problem
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
DFAEXEC8(const pcre *argument_re, const pcre_extra *extra_data,
  const char *subject, int length, int start_offset, int options, int *offsets,
  int offsetcount, int *workspace, int wscount)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
  PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
  int offsetcount, int *workspace, int wscount)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)argument_re;
dfa_match_data match_block;
dfa_match_data *md = &match_block;
BOOL utf, anchored, startline, firstline;
const pcre_uchar *current_subject, *end_subject;
const pcre_study_data *study = NULL;

const pcre_uchar *req_char_ptr;
const pcre_uint8 *start_bits = NULL;
BOOL has_first_char = FALSE;
BOOL has_req_char = FALSE;
pcre_uchar first_char = 0;
pcre_uchar first_char2 = 0;
pcre_uchar req_char = 0;
pcre_uchar req_char2 = 0;
int newline;

/* Plausibility checks */

if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
if (re == NULL || subject == NULL || workspace == NULL ||
   (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;

/* Check that the first field in the block is the magic number. If it is not,
return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
means that the pattern is likely compiled with different endianness. */

if (re->magic_number != MAGIC_NUMBER)
  return re->magic_number == REVERSED_MAGIC_NUMBER?
    PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;

/* If restarting after a partial match, do some sanity checks on the contents
of the workspace. */

if ((options & PCRE_DFA_RESTART) != 0)
  {
  if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
    workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK)
      return PCRE_ERROR_DFA_BADRESTART;
  }

/* Set up study, callout, and table data */

md->tables = re->tables;
md->callout_data = NULL;

if (extra_data != NULL)
  {
  unsigned int flags = extra_data->flags;
  if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
    study = (const pcre_study_data *)extra_data->study_data;
  if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT;
  if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
    return PCRE_ERROR_DFA_UMLIMIT;
  if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
    md->callout_data = extra_data->callout_data;
  if ((flags & PCRE_EXTRA_TABLES) != 0)
    md->tables = extra_data->tables;
  }

/* Set some local values */

current_subject = (const pcre_uchar *)subject + start_offset;
end_subject = (const pcre_uchar *)subject + length;
req_char_ptr = current_subject - 1;

#ifdef SUPPORT_UTF
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
utf = (re->options & PCRE_UTF8) != 0;
#else
utf = FALSE;
#endif

anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
  (re->options & PCRE_ANCHORED) != 0;

/* The remaining fixed data for passing around. */

md->start_code = (const pcre_uchar *)argument_re +
    re->name_table_offset + re->name_count * re->name_entry_size;
md->start_subject = (const pcre_uchar *)subject;
md->end_subject = end_subject;
md->start_offset = start_offset;
md->moptions = options;
md->poptions = re->options;

/* If the BSR option is not set at match time, copy what was set
at compile time. */

if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
  {
  if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
    md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
#ifdef BSR_ANYCRLF
  else md->moptions |= PCRE_BSR_ANYCRLF;
#endif
  }

/* Handle different types of newline. The three bits give eight cases. If
nothing is set at run time, whatever was used at compile time applies. */

switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
         PCRE_NEWLINE_BITS)
  {
  case 0: newline = NEWLINE; break;   /* Compile-time default */
  case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
  case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
  case PCRE_NEWLINE_CR+
       PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
  case PCRE_NEWLINE_ANY: newline = -1; break;
  case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
  default: return PCRE_ERROR_BADNEWLINE;
  }

if (newline == -2)
  {
  md->nltype = NLTYPE_ANYCRLF;
  }
else if (newline < 0)
  {
  md->nltype = NLTYPE_ANY;
  }
else
  {
  md->nltype = NLTYPE_FIXED;
  if (newline > 255)
    {
    md->nllen = 2;
    md->nl[0] = (newline >> 8) & 255;
    md->nl[1] = newline & 255;
    }
  else
    {
    md->nllen = 1;
    md->nl[0] = newline;
    }
  }

/* Check a UTF-8 string if required. Unfortunately there's no way of passing
back the character offset. */

#ifdef SUPPORT_UTF
if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
  {
  int erroroffset;
  int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset);
  if (errorcode != 0)
    {
    if (offsetcount >= 2)
      {
      offsets[0] = erroroffset;
      offsets[1] = errorcode;
      }
    return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0)?
      PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
    }
  if (start_offset > 0 && start_offset < length &&
        NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
    return PCRE_ERROR_BADUTF8_OFFSET;
  }
#endif

/* If the exec call supplied NULL for tables, use the inbuilt ones. This
is a feature that makes it possible to save compiled regex and re-use them
in other programs later. */

if (md->tables == NULL) md->tables = PRIV(default_tables);

/* The "must be at the start of a line" flags are used in a loop when finding
where to start. */

startline = (re->flags & PCRE_STARTLINE) != 0;
firstline = (re->options & PCRE_FIRSTLINE) != 0;

/* Set up the first character to match, if available. The first_byte value is
never set for an anchored regular expression, but the anchoring may be forced
at run time, so we have to test for anchoring. The first char may be unset for
an unanchored pattern, of course. If there's no first char and the pattern was
studied, there may be a bitmap of possible first characters. */

if (!anchored)
  {
  if ((re->flags & PCRE_FIRSTSET) != 0)
    {
    has_first_char = TRUE;
    first_char = first_char2 = (pcre_uchar)(re->first_char);
    if ((re->flags & PCRE_FCH_CASELESS) != 0)
      {
      first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
      if (utf && first_char > 127)
        first_char2 = UCD_OTHERCASE(first_char);
#endif
      }
    }
  else
    {
    if (!startline && study != NULL &&
         (study->flags & PCRE_STUDY_MAPPED) != 0)
      start_bits = study->start_bits;
    }
  }

/* For anchored or unanchored matches, there may be a "last known required
character" set. */

if ((re->flags & PCRE_REQCHSET) != 0)
  {
  has_req_char = TRUE;
  req_char = req_char2 = (pcre_uchar)(re->req_char);
  if ((re->flags & PCRE_RCH_CASELESS) != 0)
    {
    req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
    if (utf && req_char > 127)
      req_char2 = UCD_OTHERCASE(req_char);
#endif
    }
  }

/* Call the main matching function, looping for a non-anchored regex after a
failed match. If not restarting, perform certain optimizations at the start of
a match. */

for (;;)
  {
  int rc;

  if ((options & PCRE_DFA_RESTART) == 0)
    {
    const pcre_uchar *save_end_subject = end_subject;

    /* If firstline is TRUE, the start of the match is constrained to the first
    line of a multiline string. Implement this by temporarily adjusting
    end_subject so that we stop scanning at a newline. If the match fails at
    the newline, later code breaks this loop. */

    if (firstline)
      {
      PCRE_PUCHAR t = current_subject;
#ifdef SUPPORT_UTF
      if (utf)
        {
        while (t < md->end_subject && !IS_NEWLINE(t))
          {
          t++;
          ACROSSCHAR(t < end_subject, *t, t++);
          }
        }
      else
#endif
      while (t < md->end_subject && !IS_NEWLINE(t)) t++;
      end_subject = t;
      }

    /* There are some optimizations that avoid running the match if a known
    starting point is not found. However, there is an option that disables
    these, for testing and for ensuring that all callouts do actually occur.
    The option can be set in the regex by (*NO_START_OPT) or passed in
    match-time options. */

    if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
      {
      /* Advance to a known first char. */

      if (has_first_char)
        {
        if (first_char != first_char2)
          while (current_subject < end_subject &&
              *current_subject != first_char && *current_subject != first_char2)
            current_subject++;
        else
          while (current_subject < end_subject &&
                 *current_subject != first_char)
            current_subject++;
        }

      /* Or to just after a linebreak for a multiline match if possible */

      else if (startline)
        {
        if (current_subject > md->start_subject + start_offset)
          {
#ifdef SUPPORT_UTF
          if (utf)
            {
            while (current_subject < end_subject &&
                   !WAS_NEWLINE(current_subject))
              {
              current_subject++;
              ACROSSCHAR(current_subject < end_subject, *current_subject,
                current_subject++);
              }
            }
          else
#endif
          while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
            current_subject++;

          /* If we have just passed a CR and the newline option is ANY or
          ANYCRLF, and we are now at a LF, advance the match position by one
          more character. */

          if (current_subject[-1] == CHAR_CR &&
               (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
               current_subject < end_subject &&
               *current_subject == CHAR_NL)
            current_subject++;
          }
        }

      /* Or to a non-unique first char after study */

      else if (start_bits != NULL)
        {
        while (current_subject < end_subject)
          {
          register unsigned int c = *current_subject;
#ifndef COMPILE_PCRE8
          if (c > 255) c = 255;
#endif
          if ((start_bits[c/8] & (1 << (c&7))) == 0)
            {
            current_subject++;
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
            /* In non 8-bit mode, the iteration will stop for
            characters > 255 at the beginning or not stop at all. */
            if (utf)
              ACROSSCHAR(current_subject < end_subject, *current_subject,
                current_subject++);
#endif
            }
          else break;
          }
        }
      }

    /* Restore fudged end_subject */

    end_subject = save_end_subject;

    /* The following two optimizations are disabled for partial matching or if
    disabling is explicitly requested (and of course, by the test above, this
    code is not obeyed when restarting after a partial match). */

    if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 &&
        (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
      {
      /* If the pattern was studied, a minimum subject length may be set. This
      is a lower bound; no actual string of that length may actually match the
      pattern. Although the value is, strictly, in characters, we treat it as
      bytes to avoid spending too much time in this optimization. */

      if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
          (pcre_uint32)(end_subject - current_subject) < study->minlength)
        return PCRE_ERROR_NOMATCH;

      /* If req_char is set, we know that that character must appear in the
      subject for the match to succeed. If the first character is set, req_char
      must be later in the subject; otherwise the test starts at the match
      point. This optimization can save a huge amount of work in patterns with
      nested unlimited repeats that aren't going to match. Writing separate
      code for cased/caseless versions makes it go faster, as does using an
      autoincrement and backing off on a match.

      HOWEVER: when the subject string is very, very long, searching to its end
      can take a long time, and give bad performance on quite ordinary
      patterns. This showed up when somebody was matching /C/ on a 32-megabyte
      string... so we don't do this when the string is sufficiently long. */

      if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX)
        {
        register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0);

        /* We don't need to repeat the search if we haven't yet reached the
        place we found it at last time. */

        if (p > req_char_ptr)
          {
          if (req_char != req_char2)
            {
            while (p < end_subject)
              {
              register int pp = *p++;
              if (pp == req_char || pp == req_char2) { p--; break; }
              }
            }
          else
            {
            while (p < end_subject)
              {
              if (*p++ == req_char) { p--; break; }
              }
            }

          /* If we can't find the required character, break the matching loop,
          which will cause a return or PCRE_ERROR_NOMATCH. */

          if (p >= end_subject) break;

          /* If we have found the required character, save the point where we
          found it, so that we don't search again next time round the loop if
          the start hasn't passed this character yet. */

          req_char_ptr = p;
          }
        }
      }
    }   /* End of optimizations that are done when not restarting */

  /* OK, now we can do the business */

  md->start_used_ptr = current_subject;
  md->recursive = NULL;

  rc = internal_dfa_exec(
    md,                                /* fixed match data */
    md->start_code,                    /* this subexpression's code */
    current_subject,                   /* where we currently are */
    start_offset,                      /* start offset in subject */
    offsets,                           /* offset vector */
    offsetcount,                       /* size of same */
    workspace,                         /* workspace vector */
    wscount,                           /* size of same */
    0);                                /* function recurse level */

  /* Anything other than "no match" means we are done, always; otherwise, carry
  on only if not anchored. */

  if (rc != PCRE_ERROR_NOMATCH || anchored) return rc;

  /* Advance to the next subject character unless we are at the end of a line
  and firstline is set. */

  if (firstline && IS_NEWLINE(current_subject)) break;
  current_subject++;
#ifdef SUPPORT_UTF
  if (utf)
    {
    ACROSSCHAR(current_subject < end_subject, *current_subject,
      current_subject++);
    }
#endif
  if (current_subject > end_subject) break;

  /* If we have just passed a CR and we are now at a LF, and the pattern does
  not contain any explicit matches for \r or \n, and the newline option is CRLF
  or ANY or ANYCRLF, advance the match position by one more character. */

  if (current_subject[-1] == CHAR_CR &&
      current_subject < end_subject &&
      *current_subject == CHAR_NL &&
      (re->flags & PCRE_HASCRORLF) == 0 &&
        (md->nltype == NLTYPE_ANY ||
         md->nltype == NLTYPE_ANYCRLF ||
         md->nllen == 2))
    current_subject++;

  }   /* "Bumpalong" loop */

return PCRE_ERROR_NOMATCH;
}

/* End of DFAEXEC8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_dfa_exec.c converted to DFAEXEC8*/
/*autoconv-0013 DFAEXEC8 line: 41 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0010 DFAEXEC8 line: 76 added HAVE_CONFIG_H*/
/*autoconv-0011 DFAEXEC8 line: 79 config.h replaced by CONFIG.h*/
/*autoconv-0011 DFAEXEC8 line: 86 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 DFAEXEC8 line: 3138 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 DFAEXEC8 line: 3616 pcre_dfa_exec replaced by DFAEXEC8*/
./ ADD NAME=VERSION8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function VERSION8(), which returns a
string that identifies the PCRE version that is in use. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*          Return version string                 *
*************************************************/

/* These macros are the standard way of turning unquoted text into C strings.
They allow macros like PCRE_MAJOR to be defined without quotes, which is
convenient for user programs that want to test its value. */

#define STRING(a)  # a
#define XSTRING(s) STRING(s)

/* A problem turned up with PCRE_PRERELEASE, which is defined empty for
production releases. Originally, it was used naively in this code:

  return XSTRING(PCRE_MAJOR)
         "." XSTRING(PCRE_MINOR)
             XSTRING(PCRE_PRERELEASE)
         " " XSTRING(PCRE_DATE);

However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of
STRING(). The C standard states: "If (before argument substitution) any
argument consists of no preprocessing tokens, the behavior is undefined." It
turns out the gcc treats this case as a single empty string - which is what we
really want - but Visual C grumbles about the lack of an argument for the
macro. Unfortunately, both are within their rights. To cope with both ways of
handling this, I had resort to some messy hackery that does a test at run time.
I could find no way of detecting that a macro is defined as an empty string at
pre-processor time. This hack uses a standard trick for avoiding calling
the STRING macro with an empty argument when doing the test. */

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
VERSION8(void)
#else
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
pcre16_version(void)
#endif
{
return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)?
  XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) :
  XSTRING(PCRE_MAJOR.PCRE_MINOR) XSTRING(PCRE_PRERELEASE PCRE_DATE);
}

/* End of VERSION8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_version.c converted to VERSION8*/
/*autoconv-0013 VERSION8 line: 41 pcre_version replaced by VERSION8*/
/*autoconv-0010 VERSION8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 VERSION8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 VERSION8 line: 52 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 VERSION8 line: 87 pcre_version replaced by VERSION8*/
/*autoconv-0013 VERSION8 line: 98 pcre_version replaced by VERSION8*/
./ ADD NAME=CHARTAB8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* This file was automatically written by the DFTABLES auxiliary
program. It contains character tables that are used when no external
tables are passed to PCRE by the application that calls it. The tables
are used only for characters whose code values are less than 256.

The following #includes are present because without them gcc 4.x may remove
the array definition from the final binary if PCRE is built into a static
library and dead code stripping is activated. This leads to link errors.
Pulling in the header ensures that the array gets flagged as "someone
outside this compilation unit might reference this" and so it will always
be supplied to the linker. */

#ifndef HAVE_CONFIG_H
#define HAVE_CONFIG_H 1
#endif
#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

const pcre_uint8 PRIV(default_tables)[] = {

/* This table is a lower casing table. */

    0,  1,  2,  3,  4,  5,  6,  7,
    8,  9, 10, 11, 12, 13, 14, 15,
   16, 17, 18, 19, 20, 21, 22, 23,
   24, 25, 26, 27, 28, 29, 30, 31,
   32, 33, 34, 35, 36, 37, 38, 39,
   40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55,
   56, 57, 58, 59, 60, 61, 62, 63,
   64, 65, 66, 67, 68, 69, 70, 71,
   72, 73, 74, 75, 76, 77, 78, 79,
   80, 81, 82, 83, 84, 85, 86, 87,
   88, 89, 90, 91, 92, 93, 94, 95,
   96, 97, 98, 99,100,101,102,103,
  104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,
  120,121,122,123,124,125,126,127,
  128,129,130,131,132,133,134,135,
  136,137,138,139,140,141,142,143,
  144,145,146,147,148,149,150,151,
  152,153,154,155,156,157,158,159,
  160,161,162,163,164,165,166,167,
  168,169,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,
  184,185,186,187,188,189,190,191,
  192,129,130,131,132,133,134,135,
  136,137,202,203,204,205,206,207,
  208,145,146,147,148,149,150,151,
  152,153,218,219,220,221,222,223,
  224,225,162,163,164,165,166,167,
  168,169,234,235,236,237,238,239,
  240,241,242,243,244,245,246,247,
  248,249,250,251,252,253,254,255,

/* This table is a case flipping table. */

    0,  1,  2,  3,  4,  5,  6,  7,
    8,  9, 10, 11, 12, 13, 14, 15,
   16, 17, 18, 19, 20, 21, 22, 23,
   24, 25, 26, 27, 28, 29, 30, 31,
   32, 33, 34, 35, 36, 37, 38, 39,
   40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55,
   56, 57, 58, 59, 60, 61, 62, 63,
   64, 65, 66, 67, 68, 69, 70, 71,
   72, 73, 74, 75, 76, 77, 78, 79,
   80, 81, 82, 83, 84, 85, 86, 87,
   88, 89, 90, 91, 92, 93, 94, 95,
   96, 97, 98, 99,100,101,102,103,
  104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,
  120,121,122,123,124,125,126,127,
  128,193,194,195,196,197,198,199,
  200,201,138,139,140,141,142,143,
  144,209,210,211,212,213,214,215,
  216,217,154,155,156,157,158,159,
  160,161,226,227,228,229,230,231,
  232,233,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,
  184,185,186,187,188,189,190,191,
  192,129,130,131,132,133,134,135,
  136,137,202,203,204,205,206,207,
  208,145,146,147,148,149,150,151,
  152,153,218,219,220,221,222,223,
  224,225,162,163,164,165,166,167,
  168,169,234,235,236,237,238,239,
  240,241,242,243,244,245,246,247,
  248,249,250,251,252,253,254,255,

/* This table contains bit maps for various character classes.
Each map is 32 bytes long and the bits run from the least
significant end of each byte. The classes that have their own
maps are: space, xdigit, digit, upper, lower, word, graph
print, punct, and cntrl. Other classes are built from combinations. */

  0x20,0x38,0x20,0x00,0x00,0x00,0x00,0x00,
  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x7e,0x00,0x00,0x00,0x00,0x00,0xff,0x03,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0xfe,0x03,0xfe,0x03,0xfc,0x03,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0xfe,0x03,0xfe,0x03,0xfc,0x03,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,
  0xfe,0x03,0xfe,0x03,0xfc,0x03,0x00,0x00,
  0xfe,0x03,0xfe,0x03,0xfc,0x03,0xff,0x03,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0xfc,0x01,0xfc,0x03,0xfc,0x00,0xfe,
  0xfe,0x03,0xfe,0x03,0xfe,0x23,0x00,0x20,
  0xff,0x03,0xff,0x03,0xfd,0x03,0xff,0x03,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x01,0xfc,0x01,0xfc,0x03,0xfc,0x00,0xfe,
  0xfe,0x03,0xfe,0x03,0xfe,0x23,0x00,0x20,
  0xff,0x03,0xff,0x03,0xfd,0x03,0xff,0x03,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0xfc,0x01,0xfc,0x03,0xfc,0x00,0xfe,
  0x00,0x00,0x00,0x00,0x02,0x20,0x00,0x20,
  0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,

  0xff,0xff,0xff,0xff,0xff,0xfd,0xfc,0xbf,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

/* This table identifies various classes of character by individual bits:
  0x01   white space character
  0x02   letter
  0x04   decimal digit
  0x08   hexadecimal digit
  0x10   alphanumeric or '_'
  0x80   regular expression metacharacter or binary zero
*/

  0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /*   0-  7 */
  0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /*   8- 15 */
  0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /*  16- 23 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  32- 39 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  40- 47 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  48- 55 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  56- 63 */
  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*    - 71 */
  0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /*  72- |  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  & - 87 */
  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x80, /*  88-   */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  - -103 */
  0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ?  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- "  */
  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  h -143 */
  0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  q -159 */
  0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x  */
  0x12,0x12,0x00,0x00,0x00,0x80,0x00,0x00, /*  y -175 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
  0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  { - G  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  H -207 */
  0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  } - P  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  Q -223 */
  0x80,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /*  \ - X  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  Y -239 */
  0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /*  0 - 7  */
  0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/*  8 -255 */

/* End of CHARTAB8.c */
/*autoconv-0001 C:\projects\pcreport\pcre_chartables.c converted to CHARTAB8*/
/*autoconv-0010 CHARTAB8 line: 21 added HAVE_CONFIG_H*/
./ ADD NAME=COMPILE8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function COMPILE8(), along with
supporting internal functions that are not used by other modules. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#define NLBLOCK cd             /* Block containing newline information */
#define PSSTART start_pattern  /* Field containing processed string start */
#define PSEND   end_pattern    /* Field containing processed string end */

#include "INTERNA8.h"


/* When PCRE_DEBUG is defined, we need the pcre(16)_printint() function, which
is also used by PCRETEST. PCRE_DEBUG is not defined when building a production
library. We do not need to select pcre16_printint.c specially, because the
COMPILE_PCREx macro will already be appropriately set. */

#ifdef PCRE_DEBUG
/* PRINTIN8.c should not include any headers */
#define PCRE_INCLUDED
#include "PRINTIN8.c"
#undef PCRE_INCLUDED
#endif


/* Macro for setting individual bits in class bitmaps. */

#define SETBIT(a,b) a[b/8] |= (1 << (b%8))

/* Maximum length value to check against when making sure that the integer that
holds the compiled pattern length does not overflow. We make it a bit less than
INT_MAX to allow for adding in group terminating bytes, so that we don't have
to check them every time. */

#define OFLOW_MAX (INT_MAX - 20)


/*************************************************
*      Code parameters and static tables         *
*************************************************/

/* This value specifies the size of stack workspace that is used during the
first pre-compile phase that determines how much memory is required. The regex
is partly compiled into this space, but the compiled parts are discarded as
soon as they can be, so that hopefully there will never be an overrun. The code
does, however, check for an overrun. The largest amount I've seen used is 218,
so this number is very generous.

The same workspace is used during the second, actual compile phase for
remembering forward references to groups so that they can be filled in at the
end. Each entry in this list occupies LINK_SIZE bytes, so even when LINK_SIZE
is 4 there is plenty of room for most patterns. However, the memory can get
filled up by repetitions of forward references, for example patterns like
/(?1){0,1999}(b)/, and one user did hit the limit. The code has been changed so
that the workspace is expanded using malloc() in this situation. The value
below is therefore a minimum, and we put a maximum on it for safety. The
minimum is now also defined in terms of LINK_SIZE so that the use of malloc()
kicks in at the same number of forward references in all cases. */

#define COMPILE_WORK_SIZE (2048*LINK_SIZE)
#define COMPILE_WORK_SIZE_MAX (100*COMPILE_WORK_SIZE)

/* The overrun tests check for a slightly smaller size so that they detect the
overrun before it actually does run off the end of the data block. */

#define WORK_SIZE_SAFETY_MARGIN (100)

/* Private flags added to firstchar and reqchar. */

#define REQ_CASELESS   0x10000000l      /* Indicates caselessness */
#define REQ_VARY       0x20000000l      /* Reqchar followed non-literal item */

/* Repeated character flags. */

#define UTF_LENGTH     0x10000000l      /* The char contains its length. */

/* Table for handling escaped characters in the range '0'-'z'. Positive returns
are simple data values; negative values are for special things like \d and so
on. Zero means further processing is needed (for things like \x), or the escape
is invalid. */

#ifndef EBCDIC

/* This is the "normal" table for ASCII systems or for EBCDIC systems running
in UTF-8 mode. */

static const short int escapes[] = {
     0,                       0,
     0,                       0,
     0,                       0,
     0,                       0,
     0,                       0,
     CHAR_COLON,              CHAR_SEMICOLON,
     CHAR_LESS_THAN_SIGN,     CHAR_EQUALS_SIGN,
     CHAR_GREATER_THAN_SIGN,  CHAR_QUESTION_MARK,
     CHAR_COMMERCIAL_AT,      -ESC_A,
     -ESC_B,                  -ESC_C,
     -ESC_D,                  -ESC_E,
     0,                       -ESC_G,
     -ESC_H,                  0,
     0,                       -ESC_K,
     0,                       0,
     -ESC_N,                  0,
     -ESC_P,                  -ESC_Q,
     -ESC_R,                  -ESC_S,
     0,                       0,
     -ESC_V,                  -ESC_W,
     -ESC_X,                  0,
     -ESC_Z,                  CHAR_LEFT_SQUARE_BRACKET,
     CHAR_BACKSLASH,          CHAR_RIGHT_SQUARE_BRACKET,
     CHAR_CIRCUMFLEX_ACCENT,  CHAR_UNDERSCORE,
     CHAR_GRAVE_ACCENT,       7,
     -ESC_b,                  0,
     -ESC_d,                  ESC_e,
     ESC_f,                   0,
     -ESC_h,                  0,
     0,                       -ESC_k,
     0,                       0,
     ESC_n,                   0,
     -ESC_p,                  0,
     ESC_r,                   -ESC_s,
     ESC_tee,                 0,
     -ESC_v,                  -ESC_w,
     0,                       0,
     -ESC_z
};

#else

/* This is the "abnormal" table for EBCDIC systems without UTF-8 support. */

static const short int escapes[] = {
/*  48 */     0,     0,      0,     '.',    '<',   '(',    '+',    '|',
/*  50 */   '&',     0,      0,       0,      0,     0,      0,      0,
/*  58 */     0,     0,    '!',     '$',    '*',   ')',    ';',    '~',
/*  60 */   '-',   '/',      0,       0,      0,     0,      0,      0,
/*  68 */     0,     0,    '|',     ',',    '%',   '_',    '>',    '?',
/*  70 */     0,     0,      0,       0,      0,     0,      0,      0,
/*  78 */     0,   '`',    ':',     '#',    '@',  '\'',    '=',    '"',
/*  80 */     0,     7, -ESC_b,       0, -ESC_d, ESC_e,  ESC_f,      0,
/*  88 */-ESC_h,     0,      0,     '{',      0,     0,      0,      0,
/*  90 */     0,     0, -ESC_k,     'l',      0, ESC_n,      0, -ESC_p,
/*  98 */     0, ESC_r,      0,     '}',      0,     0,      0,      0,
/*  A0 */     0,   '~', -ESC_s, ESC_tee,      0,-ESC_v, -ESC_w,      0,
/*  A8 */     0,-ESC_z,      0,       0,      0,   '[',      0,      0,
/*  B0 */     0,     0,      0,       0,      0,     0,      0,      0,
/*  B8 */     0,     0,      0,       0,      0,   ']',    '=',    '-',
/*  C0 */   '{',-ESC_A, -ESC_B,  -ESC_C, -ESC_D,-ESC_E,      0, -ESC_G,
/*  C8 */-ESC_H,     0,      0,       0,      0,     0,      0,      0,
/*  D0 */   '}',     0, -ESC_K,       0,      0,-ESC_N,      0, -ESC_P,
/*  D8 */-ESC_Q,-ESC_R,      0,       0,      0,     0,      0,      0,
/*  E0 */  '\\',     0, -ESC_S,       0,      0,-ESC_V, -ESC_W, -ESC_X,
/*  E8 */     0,-ESC_Z,      0,       0,      0,     0,      0,      0,
/*  F0 */     0,     0,      0,       0,      0,     0,      0,      0,
/*  F8 */     0,     0,      0,       0,      0,     0,      0,      0
};
#endif


/* Table of special "verbs" like (*PRUNE). This is a short table, so it is
searched linearly. Put all the names into a single string, in order to reduce
the number of relocations when a shared library is dynamically linked. The
string is built from string macros so that it works in UTF-8 mode on EBCDIC
platforms. */

typedef struct verbitem {
  int   len;                 /* Length of verb name */
  int   op;                  /* Op when no arg, or -1 if arg mandatory */
  int   op_arg;              /* Op when arg present, or -1 if not allowed */
} verbitem;

static const char verbnames[] =
  "\0"                       /* Empty name is a shorthand for MARK */
  STRING_MARK0
  STRING_ACCEPT0
  STRING_COMMIT0
  STRING_F0
  STRING_FAIL0
  STRING_PRUNE0
  STRING_SKIP0
  STRING_THEN;

static const verbitem verbs[] = {
  { 0, -1,        OP_MARK },
  { 4, -1,        OP_MARK },
  { 6, OP_ACCEPT, -1 },
  { 6, OP_COMMIT, -1 },
  { 1, OP_FAIL,   -1 },
  { 4, OP_FAIL,   -1 },
  { 5, OP_PRUNE,  OP_PRUNE_ARG },
  { 4, OP_SKIP,   OP_SKIP_ARG  },
  { 4, OP_THEN,   OP_THEN_ARG  }
};

static const int verbcount = sizeof(verbs)/sizeof(verbitem);


/* Tables of names of POSIX character classes and their lengths. The names are
now all in a single string, to reduce the number of relocations when a shared
library is dynamically loaded. The list of lengths is terminated by a zero
length entry. The first three must be alpha, lower, upper, as this is assumed
for handling case independence. */

static const char posix_names[] =
  STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0
  STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0
  STRING_graph0 STRING_print0 STRING_punct0 STRING_space0
  STRING_word0  STRING_xdigit;

static const pcre_uint8 posix_name_lengths[] = {
  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };

/* Table of class bit maps for each POSIX class. Each class is formed from a
base map, with an optional addition or removal of another map. Then, for some
classes, there is some additional tweaking: for [:blank:] the vertical space
characters are removed, and for [:alpha:] and [:alnum:] the underscore
character is removed. The triples in the table consist of the base map offset,
second map offset or -1 if no second map, and a non-negative value for map
addition or a negative value for map subtraction (if there are two maps). The
absolute value of the third field has these meanings: 0 => no tweaking, 1 =>
remove vertical space characters, 2 => remove underscore. */

static const int posix_class_maps[] = {
  cbit_word,  cbit_digit, -2,             /* alpha */
  cbit_lower, -1,          0,             /* lower */
  cbit_upper, -1,          0,             /* upper */
  cbit_word,  -1,          2,             /* alnum - word without underscore */
  cbit_print, cbit_cntrl,  0,             /* ascii */
  cbit_space, -1,          1,             /* blank - a GNU extension */
  cbit_cntrl, -1,          0,             /* cntrl */
  cbit_digit, -1,          0,             /* digit */
  cbit_graph, -1,          0,             /* graph */
  cbit_print, -1,          0,             /* print */
  cbit_punct, -1,          0,             /* punct */
  cbit_space, -1,          0,             /* space */
  cbit_word,  -1,          0,             /* word - a Perl extension */
  cbit_xdigit,-1,          0              /* xdigit */
};

/* Table of substitutes for \d etc when PCRE_UCP is set. The POSIX class
substitutes must be in the order of the names, defined above, and there are
both positive and negative cases. NULL means no substitute. */

#ifdef SUPPORT_UCP
static const pcre_uchar string_PNd[]  = {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_pNd[]  = {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_PXsp[] = {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_pXsp[] = {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_PXwd[] = {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_pXwd[] = {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };

static const pcre_uchar *substitutes[] = {
  string_PNd,           /* \D */
  string_pNd,           /* \d */
  string_PXsp,          /* \S */       /* NOTE: Xsp is Perl space */
  string_pXsp,          /* \s */
  string_PXwd,          /* \W */
  string_pXwd           /* \w */
};

static const pcre_uchar string_pL[] =   {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_pLl[] =  {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_pLu[] =  {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_pXan[] = {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_h[] =    {
  CHAR_BACKSLASH, CHAR_h, '\0' };
static const pcre_uchar string_pXps[] = {
  CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_PL[] =   {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_PLl[] =  {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_PLu[] =  {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_PXan[] = {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' };
static const pcre_uchar string_H[] =    {
  CHAR_BACKSLASH, CHAR_H, '\0' };
static const pcre_uchar string_PXps[] = {
  CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
  CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' };

static const pcre_uchar *posix_substitutes[] = {
  string_pL,            /* alpha */
  string_pLl,           /* lower */
  string_pLu,           /* upper */
  string_pXan,          /* alnum */
  NULL,                 /* ascii */
  string_h,             /* blank */
  NULL,                 /* cntrl */
  string_pNd,           /* digit */
  NULL,                 /* graph */
  NULL,                 /* print */
  NULL,                 /* punct */
  string_pXps,          /* space */    /* NOTE: Xps is POSIX space */
  string_pXwd,          /* word */
  NULL,                 /* xdigit */
  /* Negated cases */
  string_PL,            /* alpha */
  string_PLl,           /* lower */
  string_PLu,           /* upper */
  string_PXan,          /* alnum */
  NULL,                 /* ascii */
  string_H,             /* blank */
  NULL,                 /* cntrl */
  string_PNd,           /* digit */
  NULL,                 /* graph */
  NULL,                 /* print */
  NULL,                 /* punct */
  string_PXps,          /* space */   /* NOTE: Xps is POSIX space */
  string_PXwd,          /* word */
  NULL                  /* xdigit */
};
#define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(pcre_uchar *))
#endif

#define STRING(a)  # a
#define XSTRING(s) STRING(s)

/* The texts of compile-time error messages. These are "char *" because they
are passed to the outside world. Do not ever re-use any error number, because
they are documented. Always add a new error instead. Messages marked DEAD below
are no longer used. This used to be a table of strings, but in order to reduce
the number of relocations needed when a shared library is loaded dynamically,
it is now one long string. We cannot use a table of offsets, because the
lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we
simply count through to the one we want - this isn't a performance issue
because these strings are used only when there is a compilation error.

Each substring ends with \0 to insert a null character. This includes the final
substring, so that the whole string ends with \0\0, which can be detected when
counting through. */

static const char error_texts[] =
  "no error\0"
  "\\ at end of pattern\0"
  "\\c at end of pattern\0"
  "unrecognized character follows \\\0"
  "numbers out of order in {} quantifier\0"
  /* 5 */
  "number too big in {} quantifier\0"
  "missing terminating ] for character class\0"
  "invalid escape sequence in character class\0"
  "range out of order in character class\0"
  "nothing to repeat\0"
  /* 10 */
  "operand of unlimited repeat could match the empty string\0"  /** DEAD **/
  "internal error: unexpected repeat\0"
  "unrecognized character after (? or (?-\0"
  "POSIX named classes are supported only within a class\0"
  "missing )\0"
  /* 15 */
  "reference to non-existent subpattern\0"
  "erroffset passed as NULL\0"
  "unknown option bit(s) set\0"
  "missing ) after comment\0"
  "parentheses nested too deeply\0"  /** DEAD **/
  /* 20 */
  "regular expression is too large\0"
  "failed to get memory\0"
  "unmatched parentheses\0"
  "internal error: code overflow\0"
  "unrecognized character after (?<\0"
  /* 25 */
  "lookbehind assertion is not fixed length\0"
  "malformed number or name after (?(\0"
  "conditional group contains more than two branches\0"
  "assertion expected after (?(\0"
  "(?R or (?[+-]digits must be followed by )\0"
  /* 30 */
  "unknown POSIX class name\0"
  "POSIX collating elements are not supported\0"
  "this version of PCRE is compiled without UTF support\0"
  "spare error\0"  /** DEAD **/
  "character value in \\x{...} sequence is too large\0"
  /* 35 */
  "invalid condition (?(0)\0"
  "\\C not allowed in lookbehind assertion\0"
  "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0"
  "number after (?C is > 255\0"
  "closing ) for (?C expected\0"
  /* 40 */
  "recursive call could loop indefinitely\0"
  "unrecognized character after (?P\0"
  "syntax error in subpattern name (missing terminator)\0"
  "two named subpatterns have the same name\0"
  "invalid UTF-8 string\0"
  /* 45 */
  "support for \\P, \\p, and \\X has not been compiled\0"
  "malformed \\P or \\p sequence\0"
  "unknown property name after \\P or \\p\0"
  "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0"
  "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
  /* 50 */
  "repeated subpattern is too long\0"    /** DEAD **/
  "octal value is greater than \\377 in 8-bit non-UTF-8 mode\0"
  "internal error: overran compiling workspace\0"
  "internal error: previously-checked referenced subpattern not found\0"
  "DEFINE group contains more than one branch\0"
  /* 55 */
  "repeating a DEFINE group is not allowed\0"  /** DEAD **/
  "inconsistent NEWLINE options\0"
  "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"
  "a numbered reference must not be zero\0"
  "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0"
  /* 60 */
  "(*VERB) not recognized\0"
  "number is too big\0"
  "subpattern name expected\0"
  "digit expected after (?+\0"
  "] is an invalid data character in JavaScript compatibility mode\0"
  /* 65 */
  "different names for subpatterns of the same number are not allowed\0"
  "(*MARK) must have an argument\0"
  "this version of PCRE is not compiled with Unicode property support\0"
  "\\c must be followed by an ASCII character\0"
  "\\k is not followed by a braced, angle-bracketed, or quoted name\0"
  /* 70 */
  "internal error: unknown opcode in find_fixedlength()\0"
  "\\N is not supported in a class\0"
  "too many forward references\0"
  "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0"
  "invalid UTF-16 string\0"
  /* 75 */
  "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"
  "character value in \\u.... sequence is too large\0"
  ;

/* Table to identify digits and hex digits. This is used when compiling
patterns. Note that the tables in chartables are dependent on the locale, and
may mark arbitrary characters as digits - but the PCRE compiling code expects
to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have
a private table here. It costs 256 bytes, but it is a lot faster than doing
character value tests (at least in some simple cases I timed), and in some
applications one wants PCRE to compile efficiently as well as match
efficiently.

For convenience, we use the same bit definitions as in chartables:

  0x04   decimal digit
  0x08   hexadecimal digit

Then we can use ctype_digit and ctype_xdigit in the code. */

/* Using a simple comparison for decimal numbers rather than a memory read
is much faster, and the resulting code is simpler (the compiler turns it
into a subtraction and unsigned comparison). */

#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9)

#ifndef EBCDIC

/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in
UTF-8 mode. */

static const pcre_uint8 digitab[] =
  {
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   8- 15 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  16- 23 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*    - '  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  ( - /  */
  0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /*  0 - 7  */
  0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /*  8 - ?  */
  0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /*  @ - G  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  H - O  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  P - W  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  X - _  */
  0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /*  ` - g  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  h - o  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  p - w  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  x -127 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */

#else

/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */

static const pcre_uint8 digitab[] =
  {
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7  0 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   8- 15    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  16- 23 10 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  32- 39 20 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  40- 47    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  48- 55 30 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  56- 63    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*    - 71 40 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  72- |     */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  & - 87 50 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  88- 95    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  - -103 60 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ?     */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- "     */
  0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g  80 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  h -143    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p  90 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  q -159    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x  A0 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  y -175    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   -183 B0 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191    */
  0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /*  { - G  C0 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  H -207    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  } - P  D0 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  Q -223    */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  \ - X  E0 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  Y -239    */
  0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /*  0 - 7  F0 */
  0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/*  8 -255    */

static const pcre_uint8 ebcdic_chartab[] = { /* chartable partial dup */
  0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /*   0-  7 */
  0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /*   8- 15 */
  0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /*  16- 23 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31 */
  0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /*  32- 39 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  40- 47 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  48- 55 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  56- 63 */
  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*    - 71 */
  0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /*  72- |  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  & - 87 */
  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /*  88- 95 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  - -103 */
  0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ?  */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- "  */
  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  h -143 */
  0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  q -159 */
  0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  y -175 */
  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   -183 */
  0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
  0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  { - G  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  H -207 */
  0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  } - P  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  Q -223 */
  0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /*  \ - X  */
  0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /*  Y -239 */
  0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /*  0 - 7  */
  0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/*  8 -255 */
#endif


/* Definition to allow mutual recursion */

static BOOL
  compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int,
    int *, int *, branch_chain *, compile_data *, int *);



/*************************************************
*            Find an error text                  *
*************************************************/

/* The error texts are now all in one long string, to save on relocations. As
some of the text is of unknown length, we can't use a table of offsets.
Instead, just count through the strings. This is not a performance issue
because it happens only when there has been a compilation error.

Argument:   the error number
Returns:    pointer to the error string
*/

static const char *
find_error_text(int n)
{
const char *s = error_texts;
for (; n > 0; n--)
  {
  while (*s++ != 0) {};
  if (*s == 0) return "Error text not found (please report)";
  }
return s;
}


/*************************************************
*           Expand the workspace                 *
*************************************************/

/* This function is called during the second compiling phase, if the number of
forward references fills the existing workspace, which is originally a block on
the stack. A larger block is obtained from malloc() unless the ultimate limit
has been reached or the increase will be rather small.

Argument: pointer to the compile data block
Returns:  0 if all went well, else an error number
*/

static int
expand_workspace(compile_data *cd)
{
pcre_uchar *newspace;
int newsize = cd->workspace_size * 2;

if (newsize > COMPILE_WORK_SIZE_MAX) newsize = COMPILE_WORK_SIZE_MAX;
if (cd->workspace_size >= COMPILE_WORK_SIZE_MAX ||
    newsize - cd->workspace_size < WORK_SIZE_SAFETY_MARGIN)
 return ERR72;

newspace = (PUBL(malloc))(IN_UCHARS(newsize));
if (newspace == NULL) return ERR21;
memcpy(newspace, cd->start_workspace, cd->workspace_size * sizeof(pcre_uchar));
cd->hwm = (pcre_uchar *)newspace + (cd->hwm - cd->start_workspace);
if (cd->workspace_size > COMPILE_WORK_SIZE)
  (PUBL(free))((void *)cd->start_workspace);
cd->start_workspace = newspace;
cd->workspace_size = newsize;
return 0;
}



/*************************************************
*            Check for counted repeat            *
*************************************************/

/* This function is called when a '{' is encountered in a place where it might
start a quantifier. It looks ahead to see if it really is a quantifier or not.
It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
where the ddds are digits.

Arguments:
  p         pointer to the first char after '{'

Returns:    TRUE or FALSE
*/

static BOOL
is_counted_repeat(const pcre_uchar *p)
{
if (!IS_DIGIT(*p)) return FALSE;
p++;
while (IS_DIGIT(*p)) p++;
if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;

if (*p++ != CHAR_COMMA) return FALSE;
if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;

if (!IS_DIGIT(*p)) return FALSE;
p++;
while (IS_DIGIT(*p)) p++;

return (*p == CHAR_RIGHT_CURLY_BRACKET);
}



/*************************************************
*            Handle escapes                      *
*************************************************/

/* This function is called when a \ has been encountered. It either returns a
positive value for a simple escape such as \n, or a negative value which
encodes one of the more complicated things such as \d. A backreference to group
n is returned as -(ESC_REF + n); ESC_REF is the highest ESC_xxx macro. When
UTF-8 is enabled, a positive value greater than 255 may be returned. On entry,
ptr is pointing at the \. On exit, it is on the final character of the escape
sequence.

Arguments:
  ptrptr         points to the pattern position pointer
  errorcodeptr   points to the errorcode variable
  bracount       number of previous extracting brackets
  options        the options bits
  isclass        TRUE if inside a character class

Returns:         zero or positive => a data character
                 negative => a special escape sequence
                 on error, errorcodeptr is set
*/

static int
check_escape(const pcre_uchar **ptrptr, int *errorcodeptr, int bracount,
  int options, BOOL isclass)
{
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
BOOL utf = (options & PCRE_UTF8) != 0;
const pcre_uchar *ptr = *ptrptr + 1;
pcre_int32 c;
int i;

GETCHARINCTEST(c, ptr);           /* Get character value, increment pointer */
ptr--;                            /* Set pointer back to the last byte */

/* If backslash is at the end of the pattern, it's an error. */

if (c == 0) *errorcodeptr = ERR1;

/* Non-alphanumerics are literals. For digits or letters, do an initial lookup
in a table. A non-zero result is something that can be returned immediately.
Otherwise further processing may be required. */

#ifndef EBCDIC  /* ASCII/UTF-8 coding */
/* Not alphanumeric */
else if (c < CHAR_0 || c > CHAR_z) {}
else if ((i = escapes[c - CHAR_0]) != 0) c = i;

#else           /* EBCDIC coding */
/* Not alphanumeric */
else if (c < 'a' || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {}
else if ((i = escapes[c - 0x48]) != 0)  c = i;
#endif

/* Escapes that need further processing, or are illegal. */

else
  {
  const pcre_uchar *oldptr;
  BOOL braced, negated;

  switch (c)
    {
    /* A number of Perl escapes are not handled by PCRE. We give an explicit
    error. */

    case CHAR_l:
    case CHAR_L:
    *errorcodeptr = ERR37;
    break;

    case CHAR_u:
    if ((options & PCRE_JAVASCRIPT_COMPAT) != 0)
      {
      /* In JavaScript, \u must be followed by four hexadecimal numbers.
      Otherwise it is a lowercase u letter. */
      if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0
        && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0
        && MAX_255(ptr[3]) && (digitab[ptr[3]] & ctype_xdigit) != 0
        && MAX_255(ptr[4]) && (digitab[ptr[4]] & ctype_xdigit) != 0)
        {
        c = 0;
        for (i = 0; i < 4; ++i)
          {
          register int cc = *(++ptr);
#ifndef EBCDIC  /* ASCII/UTF-8 coding */
          if (cc >= CHAR_a) cc -= 32;               /* Convert to upper case */
          c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
#else           /* EBCDIC coding */
          if (cc >= CHAR_a && cc <= CHAR_z) cc += 64;  /* Convert to upper case */
          c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
#endif
          }

#ifdef COMPILE_PCRE8
        if (c > (utf ? 0x10ffff : 0xff))
#else
#ifdef COMPILE_PCRE16
        if (c > (utf ? 0x10ffff : 0xffff))
#endif
#endif
          {
          *errorcodeptr = ERR76;
          }
        else if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
        }
      }
    else
      *errorcodeptr = ERR37;
    break;

    case CHAR_U:
    /* In JavaScript, \U is an uppercase U letter. */
    if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) *errorcodeptr = ERR37;
    break;

    /* In a character class, \g is just a literal "g". Outside a character
    class, \g must be followed by one of a number of specific things:

    (1) A number, either plain or braced. If positive, it is an absolute
    backreference. If negative, it is a relative backreference. This is a Perl
    5.10 feature.

    (2) Perl 5.10 also supports \g{name} as a reference to a named group. This
    is part of Perl's movement towards a unified syntax for back references. As
    this is synonymous with \k{name}, we fudge it up by pretending it really
    was \k.

    (3) For Oniguruma compatibility we also support \g followed by a name or a
    number either in angle brackets or in single quotes. However, these are
    (possibly recursive) subroutine calls, _not_ backreferences. Just return
    the -ESC_g code (cf \k). */

    case CHAR_g:
    if (isclass) break;
    if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE)
      {
      c = -ESC_g;
      break;
      }

    /* Handle the Perl-compatible cases */

    if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
      {
      const pcre_uchar *p;
      for (p = ptr+2; *p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET; p++)
        if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break;
      if (*p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET)
        {
        c = -ESC_k;
        break;
        }
      braced = TRUE;
      ptr++;
      }
    else braced = FALSE;

    if (ptr[1] == CHAR_MINUS)
      {
      negated = TRUE;
      ptr++;
      }
    else negated = FALSE;

    /* The integer range is limited by the machine's int representation. */
    c = 0;
    while (IS_DIGIT(ptr[1]))
      {
      if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */
        {
        c = -1;
        break;
        }
      c = c * 10 + *(++ptr) - CHAR_0;
      }
    if (((unsigned int)c) > INT_MAX) /* Integer overflow */
      {
      while (IS_DIGIT(ptr[1]))
        ptr++;
      *errorcodeptr = ERR61;
      break;
      }

    if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET)
      {
      *errorcodeptr = ERR57;
      break;
      }

    if (c == 0)
      {
      *errorcodeptr = ERR58;
      break;
      }

    if (negated)
      {
      if (c > bracount)
        {
        *errorcodeptr = ERR15;
        break;
        }
      c = bracount - (c - 1);
      }

    c = -(ESC_REF + c);
    break;

    /* The handling of escape sequences consisting of a string of digits
    starting with one that is not zero is not straightforward. By experiment,
    the way Perl works seems to be as follows:

    Outside a character class, the digits are read as a decimal number. If the
    number is less than 10, or if there are that many previous extracting
    left brackets, then it is a back reference. Otherwise, up to three octal
    digits are read to form an escaped byte. Thus \123 is likely to be octal
    123 (cf \0123, which is octal 012 followed by the literal 3). If the octal
    value is greater than 377, the least significant 8 bits are taken. Inside a
    character class, \ followed by a digit is always an octal number. */

    case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:
    case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:

    if (!isclass)
      {
      oldptr = ptr;
      /* The integer range is limited by the machine's int representation. */
      c -= CHAR_0;
      while (IS_DIGIT(ptr[1]))
        {
        if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */
          {
          c = -1;
          break;
          }
        c = c * 10 + *(++ptr) - CHAR_0;
        }
      if (((unsigned int)c) > INT_MAX) /* Integer overflow */
        {
        while (IS_DIGIT(ptr[1]))
          ptr++;
        *errorcodeptr = ERR61;
        break;
        }
      if (c < 10 || c <= bracount)
        {
        c = -(ESC_REF + c);
        break;
        }
      ptr = oldptr;      /* Put the pointer back and fall through */
      }

    /* Handle an octal number following \. If the first digit is 8 or 9, Perl
    generates a binary zero byte and treats the digit as a following literal.
    Thus we have to pull back the pointer by one. */

    if ((c = *ptr) >= CHAR_8)
      {
      ptr--;
      c = 0;
      break;
      }

    /* \0 always starts an octal number, but we may drop through to here with a
    larger first octal digit. The original code used just to take the least
    significant 8 bits of octal numbers (I think this is what early Perls used
    to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode,
    but no more than 3 octal digits. */

    case CHAR_0:
    c -= CHAR_0;
    while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7)
        c = c * 8 + *(++ptr) - CHAR_0;
#ifdef COMPILE_PCRE8
    if (!utf && c > 0xff) *errorcodeptr = ERR51;
#endif
    break;

    /* \x is complicated. \x{ddd} is a character number which can be greater
    than 0xff in utf or non-8bit mode, but only if the ddd are hex digits.
    If not, { is treated as a data character. */

    case CHAR_x:
    if ((options & PCRE_JAVASCRIPT_COMPAT) != 0)
      {
      /* In JavaScript, \x must be followed by two hexadecimal numbers.
      Otherwise it is a lowercase x letter. */
      if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0
        && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0)
        {
        c = 0;
        for (i = 0; i < 2; ++i)
          {
          register int cc = *(++ptr);
#ifndef EBCDIC  /* ASCII/UTF-8 coding */
          if (cc >= CHAR_a) cc -= 32;               /* Convert to upper case */
          c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
#else           /* EBCDIC coding */
          if (cc >= CHAR_a && cc <= CHAR_z) cc += 64;  /* Convert to upper case */
          c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
#endif
          }
        }
      break;
      }

    if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
      {
      const pcre_uchar *pt = ptr + 2;

      c = 0;
      while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0)
        {
        register int cc = *pt++;
        if (c == 0 && cc == CHAR_0) continue;     /* Leading zeroes */

#ifndef EBCDIC  /* ASCII/UTF-8 coding */
        if (cc >= CHAR_a) cc -= 32;               /* Convert to upper case */
        c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
#else           /* EBCDIC coding */
        if (cc >= CHAR_a && cc <= CHAR_z) cc += 64;  /* Convert to upper case */
        c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
#endif

#ifdef COMPILE_PCRE8
        if (c > (utf ? 0x10ffff : 0xff)) { c = -1; break; }
#else
#ifdef COMPILE_PCRE16
        if (c > (utf ? 0x10ffff : 0xffff)) { c = -1; break; }
#endif
#endif
        }

      if (c < 0)
        {
        while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0) pt++;
        *errorcodeptr = ERR34;
        }

      if (*pt == CHAR_RIGHT_CURLY_BRACKET)
        {
        if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
        ptr = pt;
        break;
        }

      /* If the sequence of hex digits does not end with '}', then we don't
      recognize this construct; fall through to the normal \x handling. */
      }

    /* Read just a single-byte hex-defined char */

    c = 0;
    while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0)
      {
      int cc;                                  /* Some compilers don't like */
      cc = *(++ptr);                           /* ++ in initializers */
#ifndef EBCDIC  /* ASCII/UTF-8 coding */
      if (cc >= CHAR_a) cc -= 32;              /* Convert to upper case */
      c = c * 16 + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
#else           /* EBCDIC coding */
      if (cc <= CHAR_z) cc += 64;              /* Convert to upper case */
      c = c * 16 + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
#endif
      }
    break;

    /* For \c, a following letter is upper-cased; then the 0x40 bit is flipped.
    An error is given if the byte following \c is not an ASCII character. This
    coding is ASCII-specific, but then the whole concept of \cx is
    ASCII-specific. (However, an EBCDIC equivalent has now been added.) */

    case CHAR_c:
    c = *(++ptr);
    if (c == 0)
      {
      *errorcodeptr = ERR2;
      break;
      }
#ifndef EBCDIC    /* ASCII/UTF-8 coding */
    if (c > 127)  /* Excludes all non-ASCII in either mode */
      {
      *errorcodeptr = ERR68;
      break;
      }
    if (c >= CHAR_a && c <= CHAR_z) c -= 32;
    c = 0x40;
#else             /* EBCDIC coding */
    if (c >= CHAR_a && c <= CHAR_z) c += 64;
    c = 0xC0;
#endif
    break;

    /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
    other alphanumeric following \ is an error if PCRE_EXTRA was set;
    otherwise, for Perl compatibility, it is a literal. This code looks a bit
    odd, but there used to be some cases other than the default, and there may
    be again in future, so I haven't "optimized" it. */

    default:
    if ((options & PCRE_EXTRA) != 0) switch(c)
      {
      default:
      *errorcodeptr = ERR3;
      break;
      }
    break;
    }
  }

/* Perl supports \N{name} for character names, as well as plain \N for "not
newline". PCRE does not support \N{name}. However, it does support
quantification such as \N{2,3}. */

if (c == -ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET &&
     !is_counted_repeat(ptr+2))
  *errorcodeptr = ERR37;

/* If PCRE_UCP is set, we change the values for \d etc. */

if ((options & PCRE_UCP) != 0 && c <= -ESC_D && c >= -ESC_w)
  c -= (ESC_DU - ESC_D);

/* Set the pointer to the final character before returning. */

*ptrptr = ptr;
return c;
}



#ifdef SUPPORT_UCP
/*************************************************
*               Handle \P and \p                 *
*************************************************/

/* This function is called after \P or \p has been encountered, provided that
PCRE is compiled with support for Unicode properties. On entry, ptrptr is
pointing at the P or p. On exit, it is pointing at the final character of the
escape sequence.

Argument:
  ptrptr         points to the pattern position pointer
  negptr         points to a boolean that is set TRUE for negation else FALSE
  dptr           points to an int that is set to the detailed property value
  errorcodeptr   points to the error code variable

Returns:         type value from ucp_type_table, or -1 for an invalid type
*/

static int
get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, int *dptr, int *errorcodeptr)
{
int c, i, bot, top;
const pcre_uchar *ptr = *ptrptr;
pcre_uchar name[32];

c = *(++ptr);
if (c == 0) goto ERROR_RETURN;

*negptr = FALSE;

/* \P or \p can be followed by a name in {}, optionally preceded by  for
negation. */

if (c == CHAR_LEFT_CURLY_BRACKET)
  {
  if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT)
    {
    *negptr = TRUE;
    ptr++;
    }
  for (i = 0; i < (int)(sizeof(name) / sizeof(pcre_uchar)) - 1; i++)
    {
    c = *(++ptr);
    if (c == 0) goto ERROR_RETURN;
    if (c == CHAR_RIGHT_CURLY_BRACKET) break;
    name[i] = c;
    }
  if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN;
  name[i] = 0;
  }

/* Otherwise there is just one following character */

else
  {
  name[0] = c;
  name[1] = 0;
  }

*ptrptr = ptr;

/* Search for a recognized property name using binary chop */

bot = 0;
top = PRIV(utt_size);

while (bot < top)
  {
  i = (bot + top) >> 1;
  c = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);
  if (c == 0)
    {
    *dptr = PRIV(utt)[i].value;
    return PRIV(utt)[i].type;
    }
  if (c > 0) bot = i + 1; else top = i;
  }

*errorcodeptr = ERR47;
*ptrptr = ptr;
return -1;

ERROR_RETURN:
*errorcodeptr = ERR46;
*ptrptr = ptr;
return -1;
}
#endif




/*************************************************
*         Read repeat counts                     *
*************************************************/

/* Read an item of the form {n,m} and return the values. This is called only
after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
so the syntax is guaranteed to be correct, but we need to check the values.

Arguments:
  p              pointer to first char after '{'
  minp           pointer to int for min
  maxp           pointer to int for max
                 returned as -1 if no max
  errorcodeptr   points to error code variable

Returns:         pointer to '}' on success;
                 current ptr on error, with errorcodeptr set non-zero
*/

static const pcre_uchar *
read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr)
{
int min = 0;
int max = -1;

/* Read the minimum value and do a paranoid check: a negative value indicates
an integer overflow. */

while (IS_DIGIT(*p)) min = min * 10 + *p++ - CHAR_0;
if (min < 0 || min > 65535)
  {
  *errorcodeptr = ERR5;
  return p;
  }

/* Read the maximum value if there is one, and again do a paranoid on its size.
Also, max must not be less than min. */

if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else
  {
  if (*(++p) != CHAR_RIGHT_CURLY_BRACKET)
    {
    max = 0;
    while(IS_DIGIT(*p)) max = max * 10 + *p++ - CHAR_0;
    if (max < 0 || max > 65535)
      {
      *errorcodeptr = ERR5;
      return p;
      }
    if (max < min)
      {
      *errorcodeptr = ERR4;
      return p;
      }
    }
  }

/* Fill in the required variables, and pass back the pointer to the terminating
'}'. */

*minp = min;
*maxp = max;
return p;
}



/*************************************************
*  Subroutine for finding forward reference      *
*************************************************/

/* This recursive function is called only from find_parens() below. The
top-level call starts at the beginning of the pattern. All other calls must
start at a parenthesis. It scans along a pattern's text looking for capturing
subpatterns, and counting them. If it finds a named pattern that matches the
name it is given, it returns its number. Alternatively, if the name is NULL, it
returns when it reaches a given numbered subpattern. Recursion is used to keep
track of subpatterns that reset the capturing group numbers - the (?| feature.

This function was originally called only from the second pass, in which we know
that if (?< or (?' or (?P< is encountered, the name will be correctly
terminated because that is checked in the first pass. There is now one call to
this function in the first pass, to check for a recursive back reference by
name (so that we can make the whole group atomic). In this case, we need check
only up to the current position in the pattern, and that is still OK because
and previous occurrences will have been checked. To make this work, the test
for "end of pattern" is a check against cd->end_pattern in the main loop,
instead of looking for a binary zero. This means that the special first-pass
call can adjust cd->end_pattern temporarily. (Checks for binary zero while
processing items within the loop are OK, because afterwards the main loop will
terminate.)

Arguments:
  ptrptr       address of the current character pointer (updated)
  cd           compile background data
  name         name to seek, or NULL if seeking a numbered subpattern
  lorn         name length, or subpattern number if name is NULL
  xmode        TRUE if we are in /x mode
  utf          TRUE if we are in UTF-8 / UTF-16 mode
  count        pointer to the current capturing subpattern number (updated)

Returns:       the number of the named subpattern, or -1 if not found
*/

static int
find_parens_sub(pcre_uchar **ptrptr, compile_data *cd, const pcre_uchar *name, int lorn,
  BOOL xmode, BOOL utf, int *count)
{
pcre_uchar *ptr = *ptrptr;
int start_count = *count;
int hwm_count = start_count;
BOOL dup_parens = FALSE;

/* If the first character is a parenthesis, check on the type of group we are
dealing with. The very first call may not start with a parenthesis. */

if (ptr[0] == CHAR_LEFT_PARENTHESIS)
  {
  /* Handle specials such as (*SKIP) or (*UTF8) etc. */

  if (ptr[1] == CHAR_ASTERISK) ptr += 2;

  /* Handle a normal, unnamed capturing parenthesis. */

  else if (ptr[1] != CHAR_QUESTION_MARK)
    {
    *count += 1;
    if (name == NULL && *count == lorn) return *count;
    ptr++;
    }

  /* All cases now have (? at the start. Remember when we are in a group
  where the parenthesis numbers are duplicated. */

  else if (ptr[2] == CHAR_VERTICAL_LINE)
    {
    ptr += 3;
    dup_parens = TRUE;
    }

  /* Handle comments; all characters are allowed until a ket is reached. */

  else if (ptr[2] == CHAR_NUMBER_SIGN)
    {
    for (ptr += 3; *ptr != 0; ptr++) if (*ptr == CHAR_RIGHT_PARENTHESIS) break;
    goto FAIL_EXIT;
    }

  /* Handle a condition. If it is an assertion, just carry on so that it
  is processed as normal. If not, skip to the closing parenthesis of the
  condition (there can't be any nested parens). */

  else if (ptr[2] == CHAR_LEFT_PARENTHESIS)
    {
    ptr += 2;
    if (ptr[1] != CHAR_QUESTION_MARK)
      {
      while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
      if (*ptr != 0) ptr++;
      }
    }

  /* Start with (? but not a condition. */

  else
    {
    ptr += 2;
    if (*ptr == CHAR_P) ptr++;                      /* Allow optional P */

    /* We have to disambiguate (?<! and (?<= from (?<name> for named groups */

    if ((*ptr == CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK &&
        ptr[1] != CHAR_EQUALS_SIGN) || *ptr == CHAR_APOSTROPHE)
      {
      int term;
      const pcre_uchar *thisname;
      *count += 1;
      if (name == NULL && *count == lorn) return *count;
      term = *ptr++;
      if (term == CHAR_LESS_THAN_SIGN) term = CHAR_GREATER_THAN_SIGN;
      thisname = ptr;
      while (*ptr != term) ptr++;
      if (name != NULL && lorn == ptr - thisname &&
          STRNCMP_UC_UC(name, thisname, lorn) == 0)
        return *count;
      term++;
      }
    }
  }

/* Past any initial parenthesis handling, scan for parentheses or vertical
bars. Stop if we get to cd->end_pattern. Note that this is important for the
first-pass call when this value is temporarily adjusted to stop at the current
position. So DO NOT change this to a test for binary zero. */

for (; ptr < cd->end_pattern; ptr++)
  {
  /* Skip over backslashed characters and also entire \Q...\E */

  if (*ptr == CHAR_BACKSLASH)
    {
    if (*(++ptr) == 0) goto FAIL_EXIT;
    if (*ptr == CHAR_Q) for (;;)
      {
      while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {};
      if (*ptr == 0) goto FAIL_EXIT;
      if (*(++ptr) == CHAR_E) break;
      }
    continue;
    }

  /* Skip over character classes; this logic must be similar to the way they
  are handled for real. If the first character is '', skip it. Also, if the
  first few characters (either before or after ) are \Q\E or \E we skip them
  too. This makes for compatibility with Perl. Note the use of STR macros to
  encode "Q\\E" so that it works in UTF-8 on EBCDIC platforms. */

  if (*ptr == CHAR_LEFT_SQUARE_BRACKET)
    {
    BOOL negate_class = FALSE;
    for (;;)
      {
      if (ptr[1] == CHAR_BACKSLASH)
        {
        if (ptr[2] == CHAR_E)
          ptr+= 2;
        else if (STRNCMP_UC_C8(ptr + 2,
                 STR_Q STR_BACKSLASH STR_E, 3) == 0)
          ptr += 4;
        else
          break;
        }
      else if (!negate_class && ptr[1] == CHAR_CIRCUMFLEX_ACCENT)
        {
        negate_class = TRUE;
        ptr++;
        }
      else break;
      }

    /* If the next character is ']', it is a data character that must be
    skipped, except in JavaScript compatibility mode. */

    if (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET &&
        (cd->external_options & PCRE_JAVASCRIPT_COMPAT) == 0)
      ptr++;

    while (*(++ptr) != CHAR_RIGHT_SQUARE_BRACKET)
      {
      if (*ptr == 0) return -1;
      if (*ptr == CHAR_BACKSLASH)
        {
        if (*(++ptr) == 0) goto FAIL_EXIT;
        if (*ptr == CHAR_Q) for (;;)
          {
          while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {};
          if (*ptr == 0) goto FAIL_EXIT;
          if (*(++ptr) == CHAR_E) break;
          }
        continue;
        }
      }
    continue;
    }

  /* Skip comments in /x mode */

  if (xmode && *ptr == CHAR_NUMBER_SIGN)
    {
    ptr++;
    while (*ptr != 0)
      {
      if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; }
      ptr++;
#ifdef SUPPORT_UTF
      if (utf) FORWARDCHAR(ptr);
#endif
      }
    if (*ptr == 0) goto FAIL_EXIT;
    continue;
    }

  /* Check for the special metacharacters */

  if (*ptr == CHAR_LEFT_PARENTHESIS)
    {
    int rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, count);
    if (rc > 0) return rc;
    if (*ptr == 0) goto FAIL_EXIT;
    }

  else if (*ptr == CHAR_RIGHT_PARENTHESIS)
    {
    if (dup_parens && *count < hwm_count) *count = hwm_count;
    goto FAIL_EXIT;
    }

  else if (*ptr == CHAR_VERTICAL_LINE && dup_parens)
    {
    if (*count > hwm_count) hwm_count = *count;
    *count = start_count;
    }
  }

FAIL_EXIT:
*ptrptr = ptr;
return -1;
}




/*************************************************
*       Find forward referenced subpattern       *
*************************************************/

/* This function scans along a pattern's text looking for capturing
subpatterns, and counting them. If it finds a named pattern that matches the
name it is given, it returns its number. Alternatively, if the name is NULL, it
returns when it reaches a given numbered subpattern. This is used for forward
references to subpatterns. We used to be able to start this scan from the
current compiling point, using the current count value from cd->bracount, and
do it all in a single loop, but the addition of the possibility of duplicate
subpattern numbers means that we have to scan from the very start, in order to
take account of such duplicates, and to use a recursive function to keep track
of the different types of group.

Arguments:
  cd           compile background data
  name         name to seek, or NULL if seeking a numbered subpattern
  lorn         name length, or subpattern number if name is NULL
  xmode        TRUE if we are in /x mode
  utf          TRUE if we are in UTF-8 / UTF-16 mode

Returns:       the number of the found subpattern, or -1 if not found
*/

static int
find_parens(compile_data *cd, const pcre_uchar *name, int lorn, BOOL xmode,
  BOOL utf)
{
pcre_uchar *ptr = (pcre_uchar *)cd->start_pattern;
int count = 0;
int rc;

/* If the pattern does not start with an opening parenthesis, the first call
to find_parens_sub() will scan right to the end (if necessary). However, if it
does start with a parenthesis, find_parens_sub() will return when it hits the
matching closing parens. That is why we have to have a loop. */

for (;;)
  {
  rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, &count);
  if (rc > 0 || *ptr++ == 0) break;
  }

return rc;
}




/*************************************************
*      Find first significant op code            *
*************************************************/

/* This is called by several functions that scan a compiled expression looking
for a fixed first character, or an anchoring op code etc. It skips over things
that do not influence this. For some calls, it makes sense to skip negative
forward and all backward assertions, and also the \b assertion; for others it
does not.

Arguments:
  code         pointer to the start of the group
  skipassert   TRUE if certain assertions are to be skipped

Returns:       pointer to the first significant opcode
*/

static const pcre_uchar*
first_significant_code(const pcre_uchar *code, BOOL skipassert)
{
for (;;)
  {
  switch ((int)*code)
    {
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    if (!skipassert) return code;
    do code += GET(code, 1); while (*code == OP_ALT);
    code += PRIV(OP_lengths)[*code];
    break;

    case OP_WORD_BOUNDARY:
    case OP_NOT_WORD_BOUNDARY:
    if (!skipassert) return code;
    /* Fall through */

    case OP_CALLOUT:
    case OP_CREF:
    case OP_NCREF:
    case OP_RREF:
    case OP_NRREF:
    case OP_DEF:
    code += PRIV(OP_lengths)[*code];
    break;

    default:
    return code;
    }
  }
/* Control never reaches here */
}




/*************************************************
*        Find the fixed length of a branch       *
*************************************************/

/* Scan a branch and compute the fixed length of subject that will match it,
if the length is fixed. This is needed for dealing with backward assertions.
In UTF8 mode, the result is in characters rather than bytes. The branch is
temporarily terminated with OP_END when this function is called.

This function is called when a backward assertion is encountered, so that if it
fails, the error message can point to the correct place in the pattern.
However, we cannot do this when the assertion contains subroutine calls,
because they can be forward references. We solve this by remembering this case
and doing the check at the end; a flag specifies which mode we are running in.

Arguments:
  code     points to the start of the pattern (the bracket)
  utf      TRUE in UTF-8 / UTF-16 mode
  atend    TRUE if called when the pattern is complete
  cd       the "compile data" structure

Returns:   the fixed length,
             or -1 if there is no fixed length,
             or -2 if \C was encountered (in UTF-8 mode only)
             or -3 if an OP_RECURSE item was encountered and atend is FALSE
             or -4 if an unknown opcode was encountered (internal error)
*/

static int
find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd)
{
int length = -1;

register int branchlength = 0;
register pcre_uchar *cc = code + 1 + LINK_SIZE;

/* Scan along the opcodes for this branch. If we get to the end of the
branch, check the length against that of the other branches. */

for (;;)
  {
  int d;
  pcre_uchar *ce, *cs;
  register int op = *cc;

  switch (op)
    {
    /* We only need to continue for OP_CBRA (normal capturing bracket) and
    OP_BRA (normal non-capturing bracket) because the other variants of these
    opcodes are all concerned with unlimited repeated groups, which of course
    are not of fixed length. */

    case OP_CBRA:
    case OP_BRA:
    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_COND:
    d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd);
    if (d < 0) return d;
    branchlength += d;
    do cc += GET(cc, 1); while (*cc == OP_ALT);
    cc += 1 + LINK_SIZE;
    break;

    /* Reached end of a branch; if it's a ket it is the end of a nested call.
    If it's ALT it is an alternation in a nested call. An ACCEPT is effectively
    an ALT. If it is END it's the end of the outer call. All can be handled by
    the same code. Note that we must not include the OP_KETRxxx opcodes here,
    because they all imply an unlimited repeat. */

    case OP_ALT:
    case OP_KET:
    case OP_END:
    case OP_ACCEPT:
    case OP_ASSERT_ACCEPT:
    if (length < 0) length = branchlength;
      else if (length != branchlength) return -1;
    if (*cc != OP_ALT) return length;
    cc += 1 + LINK_SIZE;
    branchlength = 0;
    break;

    /* A true recursion implies not fixed length, but a subroutine call may
    be OK. If the subroutine is a forward reference, we can't deal with
    it until the end of the pattern, so return -3. */

    case OP_RECURSE:
    if (!atend) return -3;
    cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1);  /* Start subpattern */
    do ce += GET(ce, 1); while (*ce == OP_ALT);           /* End subpattern */
    if (cc > cs && cc < ce) return -1;                    /* Recursion */
    d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd);
    if (d < 0) return d;
    branchlength += d;
    cc += 1 + LINK_SIZE;
    break;

    /* Skip over assertive subpatterns */

    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    do cc += GET(cc, 1); while (*cc == OP_ALT);
    cc += PRIV(OP_lengths)[*cc];
    break;

    /* Skip over things that don't match chars */

    case OP_MARK:
    case OP_PRUNE_ARG:
    case OP_SKIP_ARG:
    case OP_THEN_ARG:
    cc += cc[1] + PRIV(OP_lengths)[*cc];
    break;

    case OP_CALLOUT:
    case OP_CIRC:
    case OP_CIRCM:
    case OP_CLOSE:
    case OP_COMMIT:
    case OP_CREF:
    case OP_DEF:
    case OP_DOLL:
    case OP_DOLLM:
    case OP_EOD:
    case OP_EODN:
    case OP_FAIL:
    case OP_NCREF:
    case OP_NRREF:
    case OP_NOT_WORD_BOUNDARY:
    case OP_PRUNE:
    case OP_REVERSE:
    case OP_RREF:
    case OP_SET_SOM:
    case OP_SKIP:
    case OP_SOD:
    case OP_SOM:
    case OP_THEN:
    case OP_WORD_BOUNDARY:
    cc += PRIV(OP_lengths)[*cc];
    break;

    /* Handle literal characters */

    case OP_CHAR:
    case OP_CHARI:
    case OP_NOT:
    case OP_NOTI:
    branchlength++;
    cc += 2;
#ifdef SUPPORT_UTF
    if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
    break;

    /* Handle exact repetitions. The count is already in characters, but we
    need to skip over a multibyte character in UTF8 mode.  */

    case OP_EXACT:
    case OP_EXACTI:
    case OP_NOTEXACT:
    case OP_NOTEXACTI:
    branchlength += GET2(cc,1);
    cc += 2 + IMM2_SIZE;
#ifdef SUPPORT_UTF
    if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
    break;

    case OP_TYPEEXACT:
    branchlength += GET2(cc,1);
    if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2;
    cc += 1 + IMM2_SIZE + 1;
    break;

    /* Handle single-char matchers */

    case OP_PROP:
    case OP_NOTPROP:
    cc += 2;
    /* Fall through */

    case OP_HSPACE:
    case OP_VSPACE:
    case OP_NOT_HSPACE:
    case OP_NOT_VSPACE:
    case OP_NOT_DIGIT:
    case OP_DIGIT:
    case OP_NOT_WHITESPACE:
    case OP_WHITESPACE:
    case OP_NOT_WORDCHAR:
    case OP_WORDCHAR:
    case OP_ANY:
    case OP_ALLANY:
    branchlength++;
    cc++;
    break;

    /* The single-byte matcher isn't allowed. This only happens in UTF-8 mode;
    otherwise \C is coded as OP_ALLANY. */

    case OP_ANYBYTE:
    return -2;

    /* Check a class for variable quantification */

#if defined SUPPORT_UTF || defined COMPILE_PCRE16
    case OP_XCLASS:
    cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
    /* Fall through */
#endif

    case OP_CLASS:
    case OP_NCLASS:
    cc += PRIV(OP_lengths)[OP_CLASS];

    switch (*cc)
      {
      case OP_CRPLUS:
      case OP_CRMINPLUS:
      case OP_CRSTAR:
      case OP_CRMINSTAR:
      case OP_CRQUERY:
      case OP_CRMINQUERY:
      return -1;

      case OP_CRRANGE:
      case OP_CRMINRANGE:
      if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1;
      branchlength += GET2(cc,1);
      cc += 1 + 2 * IMM2_SIZE;
      break;

      default:
      branchlength++;
      }
    break;

    /* Anything else is variable length */

    case OP_ANYNL:
    case OP_BRAMINZERO:
    case OP_BRAPOS:
    case OP_BRAPOSZERO:
    case OP_BRAZERO:
    case OP_CBRAPOS:
    case OP_EXTUNI:
    case OP_KETRMAX:
    case OP_KETRMIN:
    case OP_KETRPOS:
    case OP_MINPLUS:
    case OP_MINPLUSI:
    case OP_MINQUERY:
    case OP_MINQUERYI:
    case OP_MINSTAR:
    case OP_MINSTARI:
    case OP_MINUPTO:
    case OP_MINUPTOI:
    case OP_NOTMINPLUS:
    case OP_NOTMINPLUSI:
    case OP_NOTMINQUERY:
    case OP_NOTMINQUERYI:
    case OP_NOTMINSTAR:
    case OP_NOTMINSTARI:
    case OP_NOTMINUPTO:
    case OP_NOTMINUPTOI:
    case OP_NOTPLUS:
    case OP_NOTPLUSI:
    case OP_NOTPOSPLUS:
    case OP_NOTPOSPLUSI:
    case OP_NOTPOSQUERY:
    case OP_NOTPOSQUERYI:
    case OP_NOTPOSSTAR:
    case OP_NOTPOSSTARI:
    case OP_NOTPOSUPTO:
    case OP_NOTPOSUPTOI:
    case OP_NOTQUERY:
    case OP_NOTQUERYI:
    case OP_NOTSTAR:
    case OP_NOTSTARI:
    case OP_NOTUPTO:
    case OP_NOTUPTOI:
    case OP_PLUS:
    case OP_PLUSI:
    case OP_POSPLUS:
    case OP_POSPLUSI:
    case OP_POSQUERY:
    case OP_POSQUERYI:
    case OP_POSSTAR:
    case OP_POSSTARI:
    case OP_POSUPTO:
    case OP_POSUPTOI:
    case OP_QUERY:
    case OP_QUERYI:
    case OP_REF:
    case OP_REFI:
    case OP_SBRA:
    case OP_SBRAPOS:
    case OP_SCBRA:
    case OP_SCBRAPOS:
    case OP_SCOND:
    case OP_SKIPZERO:
    case OP_STAR:
    case OP_STARI:
    case OP_TYPEMINPLUS:
    case OP_TYPEMINQUERY:
    case OP_TYPEMINSTAR:
    case OP_TYPEMINUPTO:
    case OP_TYPEPLUS:
    case OP_TYPEPOSPLUS:
    case OP_TYPEPOSQUERY:
    case OP_TYPEPOSSTAR:
    case OP_TYPEPOSUPTO:
    case OP_TYPEQUERY:
    case OP_TYPESTAR:
    case OP_TYPEUPTO:
    case OP_UPTO:
    case OP_UPTOI:
    return -1;

    /* Catch unrecognized opcodes so that when new ones are added they
    are not forgotten, as has happened in the past. */

    default:
    return -4;
    }
  }
/* Control never gets here */
}




/*************************************************
*    Scan compiled regex for specific bracket    *
*************************************************/

/* This little function scans through a compiled pattern until it finds a
capturing bracket with the given number, or, if the number is negative, an
instance of OP_REVERSE for a lookbehind. The function is global in the C sense
so that it can be called from STUDY8() when finding the minimum matching
length.

Arguments:
  code        points to start of expression
  utf         TRUE in UTF-8 / UTF-16 mode
  number      the required bracket number or negative to find a lookbehind

Returns:      pointer to the opcode for the bracket, or NULL if not found
*/

const pcre_uchar *
PRIV(find_bracket)(const pcre_uchar *code, BOOL utf, int number)
{
for (;;)
  {
  register int c = *code;

  if (c == OP_END) return NULL;

  /* XCLASS is used for classes that cannot be represented just by a bit
  map. This includes negated single high-valued characters. The length in
  the table is zero; the actual length is stored in the compiled code. */

  if (c == OP_XCLASS) code += GET(code, 1);

  /* Handle recursion */

  else if (c == OP_REVERSE)
    {
    if (number < 0) return (pcre_uchar *)code;
    code += PRIV(OP_lengths)[c];
    }

  /* Handle capturing bracket */

  else if (c == OP_CBRA || c == OP_SCBRA ||
           c == OP_CBRAPOS || c == OP_SCBRAPOS)
    {
    int n = GET2(code, 1+LINK_SIZE);
    if (n == number) return (pcre_uchar *)code;
    code += PRIV(OP_lengths)[c];
    }

  /* Otherwise, we can get the item's length from the table, except that for
  repeated character types, we have to test for \p and \P, which have an extra
  two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
  must add in its length. */

  else
    {
    switch(c)
      {
      case OP_TYPESTAR:
      case OP_TYPEMINSTAR:
      case OP_TYPEPLUS:
      case OP_TYPEMINPLUS:
      case OP_TYPEQUERY:
      case OP_TYPEMINQUERY:
      case OP_TYPEPOSSTAR:
      case OP_TYPEPOSPLUS:
      case OP_TYPEPOSQUERY:
      if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
      break;

      case OP_TYPEUPTO:
      case OP_TYPEMINUPTO:
      case OP_TYPEEXACT:
      case OP_TYPEPOSUPTO:
      if (code[1 + IMM2_SIZE] == OP_PROP
        || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2;
      break;

      case OP_MARK:
      case OP_PRUNE_ARG:
      case OP_SKIP_ARG:
      code += code[1];
      break;

      case OP_THEN_ARG:
      code += code[1];
      break;
      }

    /* Add in the fixed length from the table */

    code += PRIV(OP_lengths)[c];

  /* In UTF-8 mode, opcodes that are followed by a character may be followed by
  a multi-byte character. The length in the table is a minimum, so we have to
  arrange to skip the extra bytes. */

#ifdef SUPPORT_UTF
    if (utf) switch(c)
      {
      case OP_CHAR:
      case OP_CHARI:
      case OP_EXACT:
      case OP_EXACTI:
      case OP_UPTO:
      case OP_UPTOI:
      case OP_MINUPTO:
      case OP_MINUPTOI:
      case OP_POSUPTO:
      case OP_POSUPTOI:
      case OP_STAR:
      case OP_STARI:
      case OP_MINSTAR:
      case OP_MINSTARI:
      case OP_POSSTAR:
      case OP_POSSTARI:
      case OP_PLUS:
      case OP_PLUSI:
      case OP_MINPLUS:
      case OP_MINPLUSI:
      case OP_POSPLUS:
      case OP_POSPLUSI:
      case OP_QUERY:
      case OP_QUERYI:
      case OP_MINQUERY:
      case OP_MINQUERYI:
      case OP_POSQUERY:
      case OP_POSQUERYI:
      if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
      break;
      }
#else
    (void)(utf);  /* Keep compiler happy by referencing function argument */
#endif
    }
  }
}



/*************************************************
*   Scan compiled regex for recursion reference  *
*************************************************/

/* This little function scans through a compiled pattern until it finds an
instance of OP_RECURSE.

Arguments:
  code        points to start of expression
  utf         TRUE in UTF-8 / UTF-16 mode

Returns:      pointer to the opcode for OP_RECURSE, or NULL if not found
*/

static const pcre_uchar *
find_recurse(const pcre_uchar *code, BOOL utf)
{
for (;;)
  {
  register int c = *code;
  if (c == OP_END) return NULL;
  if (c == OP_RECURSE) return code;

  /* XCLASS is used for classes that cannot be represented just by a bit
  map. This includes negated single high-valued characters. The length in
  the table is zero; the actual length is stored in the compiled code. */

  if (c == OP_XCLASS) code += GET(code, 1);

  /* Otherwise, we can get the item's length from the table, except that for
  repeated character types, we have to test for \p and \P, which have an extra
  two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
  must add in its length. */

  else
    {
    switch(c)
      {
      case OP_TYPESTAR:
      case OP_TYPEMINSTAR:
      case OP_TYPEPLUS:
      case OP_TYPEMINPLUS:
      case OP_TYPEQUERY:
      case OP_TYPEMINQUERY:
      case OP_TYPEPOSSTAR:
      case OP_TYPEPOSPLUS:
      case OP_TYPEPOSQUERY:
      if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
      break;

      case OP_TYPEPOSUPTO:
      case OP_TYPEUPTO:
      case OP_TYPEMINUPTO:
      case OP_TYPEEXACT:
      if (code[1 + IMM2_SIZE] == OP_PROP
        || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2;
      break;

      case OP_MARK:
      case OP_PRUNE_ARG:
      case OP_SKIP_ARG:
      code += code[1];
      break;

      case OP_THEN_ARG:
      code += code[1];
      break;
      }

    /* Add in the fixed length from the table */

    code += PRIV(OP_lengths)[c];

    /* In UTF-8 mode, opcodes that are followed by a character may be followed
    by a multi-byte character. The length in the table is a minimum, so we have
    to arrange to skip the extra bytes. */

#ifdef SUPPORT_UTF
    if (utf) switch(c)
      {
      case OP_CHAR:
      case OP_CHARI:
      case OP_NOT:
      case OP_NOTI:
      case OP_EXACT:
      case OP_EXACTI:
      case OP_NOTEXACT:
      case OP_NOTEXACTI:
      case OP_UPTO:
      case OP_UPTOI:
      case OP_NOTUPTO:
      case OP_NOTUPTOI:
      case OP_MINUPTO:
      case OP_MINUPTOI:
      case OP_NOTMINUPTO:
      case OP_NOTMINUPTOI:
      case OP_POSUPTO:
      case OP_POSUPTOI:
      case OP_NOTPOSUPTO:
      case OP_NOTPOSUPTOI:
      case OP_STAR:
      case OP_STARI:
      case OP_NOTSTAR:
      case OP_NOTSTARI:
      case OP_MINSTAR:
      case OP_MINSTARI:
      case OP_NOTMINSTAR:
      case OP_NOTMINSTARI:
      case OP_POSSTAR:
      case OP_POSSTARI:
      case OP_NOTPOSSTAR:
      case OP_NOTPOSSTARI:
      case OP_PLUS:
      case OP_PLUSI:
      case OP_NOTPLUS:
      case OP_NOTPLUSI:
      case OP_MINPLUS:
      case OP_MINPLUSI:
      case OP_NOTMINPLUS:
      case OP_NOTMINPLUSI:
      case OP_POSPLUS:
      case OP_POSPLUSI:
      case OP_NOTPOSPLUS:
      case OP_NOTPOSPLUSI:
      case OP_QUERY:
      case OP_QUERYI:
      case OP_NOTQUERY:
      case OP_NOTQUERYI:
      case OP_MINQUERY:
      case OP_MINQUERYI:
      case OP_NOTMINQUERY:
      case OP_NOTMINQUERYI:
      case OP_POSQUERY:
      case OP_POSQUERYI:
      case OP_NOTPOSQUERY:
      case OP_NOTPOSQUERYI:
      if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
      break;
      }
#else
    (void)(utf);  /* Keep compiler happy by referencing function argument */
#endif
    }
  }
}



/*************************************************
*    Scan compiled branch for non-emptiness      *
*************************************************/

/* This function scans through a branch of a compiled pattern to see whether it
can match the empty string or not. It is called from could_be_empty()
below and from compile_branch() when checking for an unlimited repeat of a
group that can match nothing. Note that first_significant_code() skips over
backward and negative forward assertions when its final argument is TRUE. If we
hit an unclosed bracket, we return "empty" - this means we've struck an inner
bracket whose current branch will already have been scanned.

Arguments:
  code        points to start of search
  endcode     points to where to stop
  utf         TRUE if in UTF-8 / UTF-16 mode
  cd          contains pointers to tables etc.

Returns:      TRUE if what is matched could be empty
*/

static BOOL
could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
  BOOL utf, compile_data *cd)
{
register int c;
for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
     code < endcode;
     code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE))
  {
  const pcre_uchar *ccode;

  c = *code;

  /* Skip over forward assertions; the other assertions are skipped by
  first_significant_code() with a TRUE final argument. */

  if (c == OP_ASSERT)
    {
    do code += GET(code, 1); while (*code == OP_ALT);
    c = *code;
    continue;
    }

  /* For a recursion/subroutine call, if its end has been reached, which
  implies a backward reference subroutine call, we can scan it. If it's a
  forward reference subroutine call, we can't. To detect forward reference
  we have to scan up the list that is kept in the workspace. This function is
  called only when doing the real compile, not during the pre-compile that
  measures the size of the compiled pattern. */

  if (c == OP_RECURSE)
    {
    const pcre_uchar *scode;
    BOOL empty_branch;

    /* Test for forward reference */

    for (scode = cd->start_workspace; scode < cd->hwm; scode += LINK_SIZE)
      if (GET(scode, 0) == code + 1 - cd->start_code) return TRUE;

    /* Not a forward reference, test for completed backward reference */

    empty_branch = FALSE;
    scode = cd->start_code + GET(code, 1);
    if (GET(scode, 1) == 0) return TRUE;    /* Unclosed */

    /* Completed backwards reference */

    do
      {
      if (could_be_empty_branch(scode, endcode, utf, cd))
        {
        empty_branch = TRUE;
        break;
        }
      scode += GET(scode, 1);
      }
    while (*scode == OP_ALT);

    if (!empty_branch) return FALSE;  /* All branches are non-empty */
    continue;
    }

  /* Groups with zero repeats can of course be empty; skip them. */

  if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO ||
      c == OP_BRAPOSZERO)
    {
    code += PRIV(OP_lengths)[c];
    do code += GET(code, 1); while (*code == OP_ALT);
    c = *code;
    continue;
    }

  /* A nested group that is already marked as "could be empty" can just be
  skipped. */

  if (c == OP_SBRA  || c == OP_SBRAPOS ||
      c == OP_SCBRA || c == OP_SCBRAPOS)
    {
    do code += GET(code, 1); while (*code == OP_ALT);
    c = *code;
    continue;
    }

  /* For other groups, scan the branches. */

  if (c == OP_BRA  || c == OP_BRAPOS ||
      c == OP_CBRA || c == OP_CBRAPOS ||
      c == OP_ONCE || c == OP_ONCE_NC ||
      c == OP_COND)
    {
    BOOL empty_branch;
    if (GET(code, 1) == 0) return TRUE;    /* Hit unclosed bracket */

    /* If a conditional group has only one branch, there is a second, implied,
    empty branch, so just skip over the conditional, because it could be empty.
    Otherwise, scan the individual branches of the group. */

    if (c == OP_COND && code[GET(code, 1)] != OP_ALT)
      code += GET(code, 1);
    else
      {
      empty_branch = FALSE;
      do
        {
        if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd))
          empty_branch = TRUE;
        code += GET(code, 1);
        }
      while (*code == OP_ALT);
      if (!empty_branch) return FALSE;   /* All branches are non-empty */
      }

    c = *code;
    continue;
    }

  /* Handle the other opcodes */

  switch (c)
    {
    /* Check for quantifiers after a class. XCLASS is used for classes that
    cannot be represented just by a bit map. This includes negated single
    high-valued characters. The length in PRIV(OP_lengths)[] is zero; the
    actual length is stored in the compiled code, so we must update "code"
    here. */

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
    case OP_XCLASS:
    ccode = code += GET(code, 1);
    goto CHECK_CLASS_REPEAT;
#endif

    case OP_CLASS:
    case OP_NCLASS:
    ccode = code + PRIV(OP_lengths)[OP_CLASS];

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
    CHECK_CLASS_REPEAT:
#endif

    switch (*ccode)
      {
      case OP_CRSTAR:            /* These could be empty; continue */
      case OP_CRMINSTAR:
      case OP_CRQUERY:
      case OP_CRMINQUERY:
      break;

      default:                   /* Non-repeat => class must match */
      case OP_CRPLUS:            /* These repeats aren't empty */
      case OP_CRMINPLUS:
      return FALSE;

      case OP_CRRANGE:
      case OP_CRMINRANGE:
      if (GET2(ccode, 1) > 0) return FALSE;  /* Minimum > 0 */
      break;
      }
    break;

    /* Opcodes that must match a character */

    case OP_PROP:
    case OP_NOTPROP:
    case OP_EXTUNI:
    case OP_NOT_DIGIT:
    case OP_DIGIT:
    case OP_NOT_WHITESPACE:
    case OP_WHITESPACE:
    case OP_NOT_WORDCHAR:
    case OP_WORDCHAR:
    case OP_ANY:
    case OP_ALLANY:
    case OP_ANYBYTE:
    case OP_CHAR:
    case OP_CHARI:
    case OP_NOT:
    case OP_NOTI:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_POSPLUS:
    case OP_EXACT:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTPOSPLUS:
    case OP_NOTEXACT:
    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEPOSPLUS:
    case OP_TYPEEXACT:
    return FALSE;

    /* These are going to continue, as they may be empty, but we have to
    fudge the length for the \p and \P cases. */

    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEPOSSTAR:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    case OP_TYPEPOSQUERY:
    if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
    break;

    /* Same for these */

    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    case OP_TYPEPOSUPTO:
    if (code[1 + IMM2_SIZE] == OP_PROP
      || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2;
    break;

    /* End of branch */

    case OP_KET:
    case OP_KETRMAX:
    case OP_KETRMIN:
    case OP_KETRPOS:
    case OP_ALT:
    return TRUE;

    /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO,
    MINUPTO, and POSUPTO may be followed by a multibyte character */

#ifdef SUPPORT_UTF
    case OP_STAR:
    case OP_STARI:
    case OP_MINSTAR:
    case OP_MINSTARI:
    case OP_POSSTAR:
    case OP_POSSTARI:
    case OP_QUERY:
    case OP_QUERYI:
    case OP_MINQUERY:
    case OP_MINQUERYI:
    case OP_POSQUERY:
    case OP_POSQUERYI:
    if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);
    break;

    case OP_UPTO:
    case OP_UPTOI:
    case OP_MINUPTO:
    case OP_MINUPTOI:
    case OP_POSUPTO:
    case OP_POSUPTOI:
    if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]);
    break;
#endif

    /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument
    string. */

    case OP_MARK:
    case OP_PRUNE_ARG:
    case OP_SKIP_ARG:
    code += code[1];
    break;

    case OP_THEN_ARG:
    code += code[1];
    break;

    /* None of the remaining opcodes are required to match a character. */

    default:
    break;
    }
  }

return TRUE;
}



/*************************************************
*    Scan compiled regex for non-emptiness       *
*************************************************/

/* This function is called to check for left recursive calls. We want to check
the current branch of the current pattern to see if it could match the empty
string. If it could, we must look outwards for branches at other levels,
stopping when we pass beyond the bracket which is the subject of the recursion.
This function is called only during the real compile, not during the
pre-compile.

Arguments:
  code        points to start of the recursion
  endcode     points to where to stop (current RECURSE item)
  bcptr       points to the chain of current (unclosed) branch starts
  utf         TRUE if in UTF-8 / UTF-16 mode
  cd          pointers to tables etc

Returns:      TRUE if what is matched could be empty
*/

static BOOL
could_be_empty(const pcre_uchar *code, const pcre_uchar *endcode,
  branch_chain *bcptr, BOOL utf, compile_data *cd)
{
while (bcptr != NULL && bcptr->current_branch >= code)
  {
  if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd))
    return FALSE;
  bcptr = bcptr->outer;
  }
return TRUE;
}



/*************************************************
*           Check for POSIX class syntax         *
*************************************************/

/* This function is called when the sequence "[:" or "[." or "[=" is
encountered in a character class. It checks whether this is followed by a
sequence of characters terminated by a matching ":]" or ".]" or "=]". If we
reach an unescaped ']' without the special preceding character, return FALSE.

Originally, this function only recognized a sequence of letters between the
terminators, but it seems that Perl recognizes any sequence of characters,
though of course unknown POSIX names are subsequently rejected. Perl gives an
"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE
didn't consider this to be a POSIX class. Likewise for [:1234:].

The problem in trying to be exactly like Perl is in the handling of escapes. We
have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX
class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code
below handles the special case of \], but does not try to do any other escape
processing. This makes it different from Perl for cases such as [:l\ower:]
where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize
"l\ower". This is a lesser evil that not diagnosing bad classes when Perl does,
I think.

A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.
It seems that the appearance of a nested POSIX class supersedes an apparent
external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or
a digit.

In Perl, unescaped square brackets may also appear as part of class names. For
example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for
[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not
seem right at all. PCRE does not allow closing square brackets in POSIX class
names.

Arguments:
  ptr      pointer to the initial [
  endptr   where to return the end pointer

Returns:   TRUE or FALSE
*/

static BOOL
check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr)
{
int terminator;          /* Don't combine these lines; the Solaris cc */
terminator = *(++ptr);   /* compiler warns about "non-constant" initializer. */
for (++ptr; *ptr != 0; ptr++)
  {
  if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
    ptr++;
  else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
  else
    {
    if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
      {
      *endptr = ptr;
      return TRUE;
      }
    if (*ptr == CHAR_LEFT_SQUARE_BRACKET &&
         (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
          ptr[1] == CHAR_EQUALS_SIGN) &&
        check_posix_syntax(ptr, endptr))
      return FALSE;
    }
  }
return FALSE;
}




/*************************************************
*          Check POSIX class name                *
*************************************************/

/* This function is called to check the name given in a POSIX-style class entry
such as [:alnum:].

Arguments:
  ptr        points to the first letter
  len        the length of the name

Returns:     a value representing the name, or -1 if unknown
*/

static int
check_posix_name(const pcre_uchar *ptr, int len)
{
const char *pn = posix_names;
register int yield = 0;
while (posix_name_lengths[yield] != 0)
  {
  if (len == posix_name_lengths[yield] &&
    STRNCMP_UC_C8(ptr, pn, len) == 0) return yield;
  pn += posix_name_lengths[yield] + 1;
  yield++;
  }
return -1;
}


/*************************************************
*    Adjust OP_RECURSE items in repeated group   *
*************************************************/

/* OP_RECURSE items contain an offset from the start of the regex to the group
that is referenced. This means that groups can be replicated for fixed
repetition simply by copying (because the recursion is allowed to refer to
earlier groups that are outside the current group). However, when a group is
optional (i.e. the minimum quantifier is zero), OP_BRAZERO or OP_SKIPZERO is
inserted before it, after it has been compiled. This means that any OP_RECURSE
items within it that refer to the group itself or any contained groups have to
have their offsets adjusted. That one of the jobs of this function. Before it
is called, the partially compiled regex must be temporarily terminated with
OP_END.

This function has been extended with the possibility of forward references for
recursions and subroutine calls. It must also check the list of such references
for the group we are dealing with. If it finds that one of the recursions in
the current group is on this list, it adjusts the offset in the list, not the
value in the reference (which is a group number).

Arguments:
  group      points to the start of the group
  adjust     the amount by which the group is to be moved
  utf        TRUE in UTF-8 / UTF-16 mode
  cd         contains pointers to tables etc.
  save_hwm   the hwm forward reference pointer at the start of the group

Returns:     nothing
*/

static void
adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
  pcre_uchar *save_hwm)
{
pcre_uchar *ptr = group;

while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
  {
  int offset;
  pcre_uchar *hc;

  /* See if this recursion is on the forward reference list. If so, adjust the
  reference. */

  for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE)
    {
    offset = GET(hc, 0);
    if (cd->start_code + offset == ptr + 1)
      {
      PUT(hc, 0, offset + adjust);
      break;
      }
    }

  /* Otherwise, adjust the recursion offset if it's after the start of this
  group. */

  if (hc >= cd->hwm)
    {
    offset = GET(ptr, 1);
    if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust);
    }

  ptr += 1 + LINK_SIZE;
  }
}



/*************************************************
*        Insert an automatic callout point       *
*************************************************/

/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert
callout points before each pattern item.

Arguments:
  code           current code pointer
  ptr            current pattern pointer
  cd             pointers to tables etc

Returns:         new code pointer
*/

static pcre_uchar *
auto_callout(pcre_uchar *code, const pcre_uchar *ptr, compile_data *cd)
{
*code++ = OP_CALLOUT;
*code++ = 255;
PUT(code, 0, (int)(ptr - cd->start_pattern));  /* Pattern offset */
PUT(code, LINK_SIZE, 0);                       /* Default length */
return code + 2 * LINK_SIZE;
}



/*************************************************
*         Complete a callout item                *
*************************************************/

/* A callout item contains the length of the next item in the pattern, which
we can't fill in till after we have reached the relevant point. This is used
for both automatic and manual callouts.

Arguments:
  previous_callout   points to previous callout item
  ptr                current pattern pointer
  cd                 pointers to tables etc

Returns:             nothing
*/

static void
complete_callout(pcre_uchar *previous_callout, const pcre_uchar *ptr, compile_data *cd)
{
int length = (int)(ptr - cd->start_pattern - GET(previous_callout, 2));
PUT(previous_callout, 2 + LINK_SIZE, length);
}



#ifdef SUPPORT_UCP
/*************************************************
*           Get othercase range                  *
*************************************************/

/* This function is passed the start and end of a class range, in UTF-8 mode
with UCP support. It searches up the characters, looking for internal ranges of
characters in the "other" case. Each call returns the next one, updating the
start address.

Arguments:
  cptr        points to starting character value; updated
  d           end value
  ocptr       where to put start of othercase range
  odptr       where to put end of othercase range

Yield:        TRUE when range returned; FALSE when no more
*/

static BOOL
get_othercase_range(unsigned int *cptr, unsigned int d, unsigned int *ocptr,
  unsigned int *odptr)
{
unsigned int c, othercase, next;

for (c = *cptr; c <= d; c++)
  { if ((othercase = UCD_OTHERCASE(c)) != c) break; }

if (c > d) return FALSE;

*ocptr = othercase;
next = othercase + 1;

for (++c; c <= d; c++)
  {
  if (UCD_OTHERCASE(c) != next) break;
  next++;
  }

*odptr = next - 1;
*cptr = c;

return TRUE;
}



/*************************************************
*        Check a character and a property        *
*************************************************/

/* This function is called by check_auto_possessive() when a property item
is adjacent to a fixed character.

Arguments:
  c            the character
  ptype        the property type
  pdata        the data for the type
  negated      TRUE if it's a negated property (\P or \p{)

Returns:       TRUE if auto-possessifying is OK
*/

static BOOL
check_char_prop(int c, int ptype, int pdata, BOOL negated)
{
const ucd_record *prop = GET_UCD(c);
switch(ptype)
  {
  case PT_LAMP:
  return (prop->chartype == ucp_Lu ||
          prop->chartype == ucp_Ll ||
          prop->chartype == ucp_Lt) == negated;

  case PT_GC:
  return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated;

  case PT_PC:
  return (pdata == prop->chartype) == negated;

  case PT_SC:
  return (pdata == prop->script) == negated;

  /* These are specials */

  case PT_ALNUM:
  return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
          PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated;

  case PT_SPACE:    /* Perl space */
  return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
          c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
          == negated;

  case PT_PXSPACE:  /* POSIX space */
  return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
          c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
          c == CHAR_FF || c == CHAR_CR)
          == negated;

  case PT_WORD:
  return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
          PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
          c == CHAR_UNDERSCORE) == negated;
  }
return FALSE;
}
#endif  /* SUPPORT_UCP */



/*************************************************
*     Check if auto-possessifying is possible    *
*************************************************/

/* This function is called for unlimited repeats of certain items, to see
whether the next thing could possibly match the repeated item. If not, it makes
sense to automatically possessify the repeated item.

Arguments:
  previous      pointer to the repeated opcode
  utf           TRUE in UTF-8 / UTF-16 mode
  ptr           next character in pattern
  options       options bits
  cd            contains pointers to tables etc.

Returns:        TRUE if possessifying is wanted
*/

static BOOL
check_auto_possessive(const pcre_uchar *previous, BOOL utf,
  const pcre_uchar *ptr, int options, compile_data *cd)
{
pcre_int32 c, next;
int op_code = *previous++;

/* Skip whitespace and comments in extended mode */

if ((options & PCRE_EXTENDED) != 0)
  {
  for (;;)
    {
    while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++;
    if (*ptr == CHAR_NUMBER_SIGN)
      {
      ptr++;
      while (*ptr != 0)
        {
        if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; }
        ptr++;
#ifdef SUPPORT_UTF
        if (utf) FORWARDCHAR(ptr);
#endif
        }
      }
    else break;
    }
  }

/* If the next item is one that we can handle, get its value. A non-negative
value is a character, a negative value is an escape value. */

if (*ptr == CHAR_BACKSLASH)
  {
  int temperrorcode = 0;
  next = check_escape(&ptr, &temperrorcode, cd->bracount, options, FALSE);
  if (temperrorcode != 0) return FALSE;
  ptr++;    /* Point after the escape sequence */
  }
else if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_meta) == 0)
  {
#ifdef SUPPORT_UTF
  if (utf) { GETCHARINC(next, ptr); } else
#endif
  next = *ptr++;
  }
else return FALSE;

/* Skip whitespace and comments in extended mode */

if ((options & PCRE_EXTENDED) != 0)
  {
  for (;;)
    {
    while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++;
    if (*ptr == CHAR_NUMBER_SIGN)
      {
      ptr++;
      while (*ptr != 0)
        {
        if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; }
        ptr++;
#ifdef SUPPORT_UTF
        if (utf) FORWARDCHAR(ptr);
#endif
        }
      }
    else break;
    }
  }

/* If the next thing is itself optional, we have to give up. */

if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK ||
  STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0)
    return FALSE;

/* Now compare the next item with the previous opcode. First, handle cases when
the next item is a character. */

if (next >= 0) switch(op_code)
  {
  case OP_CHAR:
#ifdef SUPPORT_UTF
  GETCHARTEST(c, previous);
#else
  c = *previous;
#endif
  return c != next;

  /* For CHARI (caseless character) we must check the other case. If we have
  Unicode property support, we can use it to test the other case of
  high-valued characters. */

  case OP_CHARI:
#ifdef SUPPORT_UTF
  GETCHARTEST(c, previous);
#else
  c = *previous;
#endif
  if (c == next) return FALSE;
#ifdef SUPPORT_UTF
  if (utf)
    {
    unsigned int othercase;
    if (next < 128) othercase = cd->fcc[next]; else
#ifdef SUPPORT_UCP
    othercase = UCD_OTHERCASE((unsigned int)next);
#else
    othercase = NOTACHAR;
#endif
    return (unsigned int)c != othercase;
    }
  else
#endif  /* SUPPORT_UTF */
  return (c != TABLE_GET((unsigned int)next, cd->fcc, next));  /* Non-UTF-8 mode */

  case OP_NOT:
#ifdef SUPPORT_UTF
  GETCHARTEST(c, previous);
#else
  c = *previous;
#endif
  return c == next;

  case OP_NOTI:
#ifdef SUPPORT_UTF
  GETCHARTEST(c, previous);
#else
  c = *previous;
#endif
  if (c == next) return TRUE;
#ifdef SUPPORT_UTF
  if (utf)
    {
    unsigned int othercase;
    if (next < 128) othercase = cd->fcc[next]; else
#ifdef SUPPORT_UCP
    othercase = UCD_OTHERCASE((unsigned int)next);
#else
    othercase = NOTACHAR;
#endif
    return (unsigned int)c == othercase;
    }
  else
#endif  /* SUPPORT_UTF */
  return (c == TABLE_GET((unsigned int)next, cd->fcc, next));  /* Non-UTF-8 mode */

  /* 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 > 255 || (cd->ctypes[next] & ctype_digit) == 0;

  case OP_NOT_DIGIT:
  return next <= 255 && (cd->ctypes[next] & ctype_digit) != 0;

  case OP_WHITESPACE:
  return next > 255 || (cd->ctypes[next] & ctype_space) == 0;

  case OP_NOT_WHITESPACE:
  return next <= 255 && (cd->ctypes[next] & ctype_space) != 0;

  case OP_WORDCHAR:
  return next > 255 || (cd->ctypes[next] & ctype_word) == 0;

  case OP_NOT_WORDCHAR:
  return next <= 255 && (cd->ctypes[next] & ctype_word) != 0;

  case OP_HSPACE:
  case OP_NOT_HSPACE:
  switch(next)
    {
    case 0x09:
    case 0x20:
    case 0xa0:
    case 0x1680:
    case 0x180e:
    case 0x2000:
    case 0x2001:
    case 0x2002:
    case 0x2003:
    case 0x2004:
    case 0x2005:
    case 0x2006:
    case 0x2007:
    case 0x2008:
    case 0x2009:
    case 0x200A:
    case 0x202f:
    case 0x205f:
    case 0x3000:
    return op_code == OP_NOT_HSPACE;
    default:
    return op_code != OP_NOT_HSPACE;
    }

  case OP_ANYNL:
  case OP_VSPACE:
  case OP_NOT_VSPACE:
  switch(next)
    {
    case 0x0a:
    case 0x0b:
    case 0x0c:
    case 0x0d:
    case 0x85:
    case 0x2028:
    case 0x2029:
    return op_code == OP_NOT_VSPACE;
    default:
    return op_code != OP_NOT_VSPACE;
    }

#ifdef SUPPORT_UCP
  case OP_PROP:
  return check_char_prop(next, previous[0], previous[1], FALSE);

  case OP_NOTPROP:
  return check_char_prop(next, previous[0], previous[1], TRUE);
#endif

  default:
  return FALSE;
  }


/* Handle the case when the next item is \d, \s, etc. Note that when PCRE_UCP
is set, \d turns into ESC_du rather than ESC_d, etc., so ESC_d etc. are
generated only when PCRE_UCP is *not* set, that is, when only ASCII
characteristics are recognized. Similarly, the opcodes OP_DIGIT etc. are
replaced by OP_PROP codes when PCRE_UCP is set. */

switch(op_code)
  {
  case OP_CHAR:
  case OP_CHARI:
#ifdef SUPPORT_UTF
  GETCHARTEST(c, previous);
#else
  c = *previous;
#endif
  switch(-next)
    {
    case ESC_d:
    return c > 255 || (cd->ctypes[c] & ctype_digit) == 0;

    case ESC_D:
    return c <= 255 && (cd->ctypes[c] & ctype_digit) != 0;

    case ESC_s:
    return c > 255 || (cd->ctypes[c] & ctype_space) == 0;

    case ESC_S:
    return c <= 255 && (cd->ctypes[c] & ctype_space) != 0;

    case ESC_w:
    return c > 255 || (cd->ctypes[c] & ctype_word) == 0;

    case ESC_W:
    return c <= 255 && (cd->ctypes[c] & ctype_word) != 0;

    case ESC_h:
    case ESC_H:
    switch(c)
      {
      case 0x09:
      case 0x20:
      case 0xa0:
      case 0x1680:
      case 0x180e:
      case 0x2000:
      case 0x2001:
      case 0x2002:
      case 0x2003:
      case 0x2004:
      case 0x2005:
      case 0x2006:
      case 0x2007:
      case 0x2008:
      case 0x2009:
      case 0x200A:
      case 0x202f:
      case 0x205f:
      case 0x3000:
      return -next != ESC_h;
      default:
      return -next == ESC_h;
      }

    case ESC_v:
    case ESC_V:
    switch(c)
      {
      case 0x0a:
      case 0x0b:
      case 0x0c:
      case 0x0d:
      case 0x85:
      case 0x2028:
      case 0x2029:
      return -next != ESC_v;
      default:
      return -next == ESC_v;
      }

    /* When PCRE_UCP is set, these values get generated for \d etc. Find
    their substitutions and process them. The result will always be either
    -ESC_p or -ESC_P. Then fall through to process those values. */

#ifdef SUPPORT_UCP
    case ESC_du:
    case ESC_DU:
    case ESC_wu:
    case ESC_WU:
    case ESC_su:
    case ESC_SU:
      {
      int temperrorcode = 0;
      ptr = substitutes[-next - ESC_DU];
      next = check_escape(&ptr, &temperrorcode, 0, options, FALSE);
      if (temperrorcode != 0) return FALSE;
      ptr++;    /* For compatibility */
      }
    /* Fall through */

    case ESC_p:
    case ESC_P:
      {
      int ptype, pdata, errorcodeptr;
      BOOL negated;

      ptr--;      /* Make ptr point at the p or P */
      ptype = get_ucp(&ptr, &negated, &pdata, &errorcodeptr);
      if (ptype < 0) return FALSE;
      ptr++;      /* Point past the final curly ket */

      /* If the property item is optional, we have to give up. (When generated
      from \d etc by PCRE_UCP, this test will have been applied much earlier,
      to the original \d etc. At this point, ptr will point to a zero byte. */

      if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK ||
        STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0)
          return FALSE;

      /* Do the property check. */

      return check_char_prop(c, ptype, pdata, (next == -ESC_P) != negated);
      }
#endif

    default:
    return FALSE;
    }

  /* In principle, support for Unicode properties should be integrated here as
  well. It means re-organizing the above code so as to get hold of the property
  values before switching on the op-code. However, I wonder how many patterns
  combine ASCII \d etc with Unicode properties? (Note that if PCRE_UCP is set,
  these op-codes are never generated.) */

  case OP_DIGIT:
  return next == -ESC_D || next == -ESC_s || next == -ESC_W ||
         next == -ESC_h || next == -ESC_v || next == -ESC_R;

  case OP_NOT_DIGIT:
  return next == -ESC_d;

  case OP_WHITESPACE:
  return next == -ESC_S || next == -ESC_d || next == -ESC_w;

  case OP_NOT_WHITESPACE:
  return next == -ESC_s || next == -ESC_h || next == -ESC_v || next == -ESC_R;

  case OP_HSPACE:
  return next == -ESC_S || next == -ESC_H || next == -ESC_d ||
         next == -ESC_w || next == -ESC_v || next == -ESC_R;

  case OP_NOT_HSPACE:
  return next == -ESC_h;

  /* Can't have \S in here because VT matches \S (Perl anomaly) */
  case OP_ANYNL:
  case OP_VSPACE:
  return next == -ESC_V || next == -ESC_d || next == -ESC_w;

  case OP_NOT_VSPACE:
  return next == -ESC_v || next == -ESC_R;

  case OP_WORDCHAR:
  return next == -ESC_W || next == -ESC_s || next == -ESC_h ||
         next == -ESC_v || next == -ESC_R;

  case OP_NOT_WORDCHAR:
  return next == -ESC_w || next == -ESC_d;

  default:
  return FALSE;
  }

/* Control does not reach here */
}



/*************************************************
*           Compile one branch                   *
*************************************************/

/* Scan the pattern, compiling it into the a vector. If the options are
changed during the branch, the pointer is used to change the external options
bits. This function is used during the pre-compile phase when we are trying
to find out the amount of memory needed, as well as during the real compile
phase. The value of lengthptr distinguishes the two phases.

Arguments:
  optionsptr     pointer to the option bits
  codeptr        points to the pointer to the current code point
  ptrptr         points to the current pattern pointer
  errorcodeptr   points to error code variable
  firstcharptr   set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
  reqcharptr     set to the last literal character required, else < 0
  bcptr          points to current branch chain
  cond_depth     conditional nesting depth
  cd             contains pointers to tables etc.
  lengthptr      NULL during the real compile phase
                 points to length accumulator during pre-compile phase

Returns:         TRUE on success
                 FALSE, with *errorcodeptr set non-zero on error
*/

static BOOL
compile_branch(int *optionsptr, pcre_uchar **codeptr,
  const pcre_uchar **ptrptr, int *errorcodeptr, pcre_int32 *firstcharptr,
  pcre_int32 *reqcharptr, branch_chain *bcptr, int cond_depth,
  compile_data *cd, int *lengthptr)
{
int repeat_type, op_type;
int repeat_min = 0, repeat_max = 0;      /* To please picky compilers */
int bravalue = 0;
int greedy_default, greedy_non_default;
pcre_int32 firstchar, reqchar;
pcre_int32 zeroreqchar, zerofirstchar;
pcre_int32 req_caseopt, reqvary, tempreqvary;
int options = *optionsptr;               /* May change dynamically */
int after_manual_callout = 0;
int length_prevgroup = 0;
register int c;
register pcre_uchar *code = *codeptr;
pcre_uchar *last_code = code;
pcre_uchar *orig_code = code;
pcre_uchar *tempcode;
BOOL inescq = FALSE;
BOOL groupsetfirstchar = FALSE;
const pcre_uchar *ptr = *ptrptr;
const pcre_uchar *tempptr;
const pcre_uchar *nestptr = NULL;
pcre_uchar *previous = NULL;
pcre_uchar *previous_callout = NULL;
pcre_uchar *save_hwm = NULL;
pcre_uint8 classbits[32];

/* We can fish out the UTF-8 setting once and for all into a BOOL, but we
must not do this for other options (e.g. PCRE_EXTENDED) because they may change
dynamically as we process the pattern. */

#ifdef SUPPORT_UTF
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
BOOL utf = (options & PCRE_UTF8) != 0;
pcre_uchar utf_chars[6];
#else
BOOL utf = FALSE;
#endif

/* Helper variables for OP_XCLASS opcode (for characters > 255). */

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
BOOL xclass;
pcre_uchar *class_uchardata;
pcre_uchar *class_uchardata_base;
#endif

#ifdef PCRE_DEBUG
if (lengthptr != NULL) DPRINTF((">> start branch\n"));
#endif

/* Set up the default and non-default settings for greediness */

greedy_default = ((options & PCRE_UNGREEDY) != 0);
greedy_non_default = greedy_default  1;

/* Initialize no first byte, no required byte. REQ_UNSET means "no char
matching encountered yet". It gets changed to REQ_NONE if we hit something that
matches a non-fixed char first char; reqchar just remains unset if we never
find one.

When we hit a repeat whose minimum is zero, we may have to adjust these values
to take the zero repeat into account. This is implemented by setting them to
zerofirstbyte and zeroreqchar when such a repeat is encountered. The individual
item types that can be repeated set these backoff variables appropriately. */

firstchar = reqchar = zerofirstchar = zeroreqchar = REQ_UNSET;

/* The variable req_caseopt contains either the REQ_CASELESS value
or zero, according to the current setting of the caseless flag. The
REQ_CASELESS leaves the lower 28 bit empty. It is added into the
firstchar or reqchar variables to record the case status of the
value. This is used only for ASCII characters. */

req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS:0;

/* Switch on next character until the end of the branch */

for (;; ptr++)
  {
  BOOL negate_class;
  BOOL should_flip_negation;
  BOOL possessive_quantifier;
  BOOL is_quantifier;
  BOOL is_recurse;
  BOOL reset_bracount;
  int class_has_8bitchar;
  int class_single_char;
  int newoptions;
  int recno;
  int refsign;
  int skipbytes;
  int subreqchar;
  int subfirstchar;
  int terminator;
  int mclength;
  int tempbracount;
  pcre_uchar mcbuffer[8];

  /* Get next character in the pattern */

  c = *ptr;

  /* If we are at the end of a nested substitution, revert to the outer level
  string. Nesting only happens one level deep. */

  if (c == 0 && nestptr != NULL)
    {
    ptr = nestptr;
    nestptr = NULL;
    c = *ptr;
    }

  /* If we are in the pre-compile phase, accumulate the length used for the
  previous cycle of this loop. */

  if (lengthptr != NULL)
    {
#ifdef PCRE_DEBUG
    if (code > cd->hwm) cd->hwm = code;                 /* High water info */
#endif
    if (code > cd->start_workspace + cd->workspace_size -
        WORK_SIZE_SAFETY_MARGIN)                       /* Check for overrun */
      {
      *errorcodeptr = ERR52;
      goto FAILED;
      }

    /* There is at least one situation where code goes backwards: this is the
    case of a zero quantifier after a class (e.g. [ab]{0}). At compile time,
    the class is simply eliminated. However, it is created first, so we have to
    allow memory for it. Therefore, don't ever reduce the length at this point.
    */

    if (code < last_code) code = last_code;

    /* Paranoid check for integer overflow */

    if (OFLOW_MAX - *lengthptr < code - last_code)
      {
      *errorcodeptr = ERR20;
      goto FAILED;
      }

    *lengthptr += (int)(code - last_code);
    DPRINTF(("length=%d added %d c=%c (0x%x)\n", *lengthptr,
      (int)(code - last_code), c, c));

    /* If "previous" is set and it is not at the start of the work space, move
    it back to there, in order to avoid filling up the work space. Otherwise,
    if "previous" is NULL, reset the current code pointer to the start. */

    if (previous != NULL)
      {
      if (previous > orig_code)
        {
        memmove(orig_code, previous, IN_UCHARS(code - previous));
        code -= previous - orig_code;
        previous = orig_code;
        }
      }
    else code = orig_code;

    /* Remember where this code item starts so we can pick up the length
    next time round. */

    last_code = code;
    }

  /* In the real compile phase, just check the workspace used by the forward
  reference list. */

  else if (cd->hwm > cd->start_workspace + cd->workspace_size -
           WORK_SIZE_SAFETY_MARGIN)
    {
    *errorcodeptr = ERR52;
    goto FAILED;
    }

  /* If in \Q...\E, check for the end; if not, we have a literal */

  if (inescq && c != 0)
    {
    if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
      {
      inescq = FALSE;
      ptr++;
      continue;
      }
    else
      {
      if (previous_callout != NULL)
        {
        if (lengthptr == NULL)  /* Don't attempt in pre-compile phase */
          complete_callout(previous_callout, ptr, cd);
        previous_callout = NULL;
        }
      if ((options & PCRE_AUTO_CALLOUT) != 0)
        {
        previous_callout = code;
        code = auto_callout(code, ptr, cd);
        }
      goto NORMAL_CHAR;
      }
    }

  /* Fill in length of a previous callout, except when the next thing is
  a quantifier. */

  is_quantifier =
    c == CHAR_ASTERISK || c == CHAR_PLUS || c == CHAR_QUESTION_MARK ||
    (c == CHAR_LEFT_CURLY_BRACKET && is_counted_repeat(ptr+1));

  if (!is_quantifier && previous_callout != NULL &&
       after_manual_callout-- <= 0)
    {
    if (lengthptr == NULL)      /* Don't attempt in pre-compile phase */
      complete_callout(previous_callout, ptr, cd);
    previous_callout = NULL;
    }

  /* In extended mode, skip white space and comments. */

  if ((options & PCRE_EXTENDED) != 0)
    {
    if (MAX_255(*ptr) && (cd->ctypes[c] & ctype_space) != 0) continue;
    if (c == CHAR_NUMBER_SIGN)
      {
      ptr++;
      while (*ptr != 0)
        {
        if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; }
        ptr++;
#ifdef SUPPORT_UTF
        if (utf) FORWARDCHAR(ptr);
#endif
        }
      if (*ptr != 0) continue;

      /* Else fall through to handle end of string */
      c = 0;
      }
    }

  /* No auto callout for quantifiers. */

  if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier)
    {
    previous_callout = code;
    code = auto_callout(code, ptr, cd);
    }

  switch(c)
    {
    /* ===================================================================*/
    case 0:                        /* The branch terminates at string end */
    case CHAR_VERTICAL_LINE:       /* or | or ) */
    case CHAR_RIGHT_PARENTHESIS:
    *firstcharptr = firstchar;
    *reqcharptr = reqchar;
    *codeptr = code;
    *ptrptr = ptr;
    if (lengthptr != NULL)
      {
      if (OFLOW_MAX - *lengthptr < code - last_code)
        {
        *errorcodeptr = ERR20;
        goto FAILED;
        }
      *lengthptr += (int)(code - last_code);   /* To include callout length */
      DPRINTF((">> end branch\n"));
      }
    return TRUE;


    /* ===================================================================*/
    /* Handle single-character metacharacters. In multiline mode,  disables
    the setting of any following char as a first character. */

    case CHAR_CIRCUMFLEX_ACCENT:
    previous = NULL;
    if ((options & PCRE_MULTILINE) != 0)
      {
      if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
      *code++ = OP_CIRCM;
      }
    else *code++ = OP_CIRC;
    break;

    case CHAR_DOLLAR_SIGN:
    previous = NULL;
    *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;
    break;

    /* There can never be a first char if '.' is first, whatever happens about
    repeats. The value of reqchar doesn't change either. */

    case CHAR_DOT:
    if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
    zerofirstchar = firstchar;
    zeroreqchar = reqchar;
    previous = code;
    *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY;
    break;


    /* ===================================================================*/
    /* Character classes. If the included characters are all < 256, we build a
    32-byte bitmap of the permitted characters, except in the special case
    where there is only one such character. For negated classes, we build the
    map as usual, then invert it at the end. However, we use a different opcode
    so that data characters > 255 can be handled correctly.

    If the class contains characters outside the 0-255 range, a different
    opcode is compiled. It may optionally have a bit map for characters < 256,
    but those above are are explicitly listed afterwards. A flag byte tells
    whether the bitmap is present, and whether this is a negated class or not.

    In JavaScript compatibility mode, an isolated ']' causes an error. In
    default (Perl) mode, it is treated as a data character. */

    case CHAR_RIGHT_SQUARE_BRACKET:
    if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
      {
      *errorcodeptr = ERR64;
      goto FAILED;
      }
    goto NORMAL_CHAR;

    case CHAR_LEFT_SQUARE_BRACKET:
    previous = code;

    /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
    they are encountered at the top level, so we'll do that too. */

    if ((ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
         ptr[1] == CHAR_EQUALS_SIGN) &&
        check_posix_syntax(ptr, &tempptr))
      {
      *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR13 : ERR31;
      goto FAILED;
      }

    /* If the first character is '', set the negation flag and skip it. Also,
    if the first few characters (either before or after ) are \Q\E or \E we
    skip them too. This makes for compatibility with Perl. */

    negate_class = FALSE;
    for (;;)
      {
      c = *(++ptr);
      if (c == CHAR_BACKSLASH)
        {
        if (ptr[1] == CHAR_E)
          ptr++;
        else if (STRNCMP_UC_C8(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0)
          ptr += 3;
        else
          break;
        }
      else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)
        negate_class = TRUE;
      else break;
      }

    /* Empty classes are allowed in JavaScript compatibility mode. Otherwise,
    an initial ']' is taken as a data character -- the code below handles
    that. In JS mode, [] must always fail, so generate OP_FAIL, whereas
    [] must match any character, so generate OP_ALLANY. */

    if (c == CHAR_RIGHT_SQUARE_BRACKET &&
        (cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
      {
      *code++ = negate_class? OP_ALLANY : OP_FAIL;
      if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
      zerofirstchar = firstchar;
      break;
      }

    /* If a class contains a negative special such as \S, we need to flip the
    negation flag at the end, so that support for characters > 255 works
    correctly (they are all included in the class). */

    should_flip_negation = FALSE;

    /* For optimization purposes, we track some properties of the class.
    class_has_8bitchar will be non-zero, if the class contains at least one
    < 256 character. class_single_char will be 1 if the class contains only
    a single character. */

    class_has_8bitchar = 0;
    class_single_char = 0;

    /* Initialize the 32-char bit map to all zeros. We build the map in a
    temporary bit of memory, in case the class contains only 1 character (less
    than 256), because in that case the compiled code doesn't use the bit map.
    */

    memset(classbits, 0, 32 * sizeof(pcre_uint8));

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
    xclass = FALSE;                           /* No chars >= 256 */
    class_uchardata = code + LINK_SIZE + 2;   /* For UTF-8 items */
    class_uchardata_base = class_uchardata;   /* For resetting in pass 1 */
#endif

    /* Process characters until ] is reached. By writing this as a "do" it
    means that an initial ] is taken as a data character. At the start of the
    loop, c contains the first byte of the character. */

    if (c != 0) do
      {
      const pcre_uchar *oldptr;

#ifdef SUPPORT_UTF
      if (utf && HAS_EXTRALEN(c))
        {                           /* Braces are required because the */
        GETCHARLEN(c, ptr, ptr);    /* macro generates multiple statements */
        }
#endif

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
      /* In the pre-compile phase, accumulate the length of any extra
      data and reset the pointer. This is so that very large classes that
      contain a zillion > 255 characters no longer overwrite the work space
      (which is on the stack). */

      if (lengthptr != NULL)
        {
        *lengthptr += class_uchardata - class_uchardata_base;
        class_uchardata = class_uchardata_base;
        }
#endif

      /* Inside \Q...\E everything is literal except \E */

      if (inescq)
        {
        if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)  /* If we are at \E */
          {
          inescq = FALSE;                   /* Reset literal state */
          ptr++;                            /* Skip the 'E' */
          continue;                         /* Carry on with next */
          }
        goto CHECK_RANGE;                   /* Could be range if \E follows */
        }

      /* Handle POSIX class names. Perl allows a negation extension of the
      form [:name:]. A square bracket that doesn't match the syntax is
      treated as a literal. We also recognize the POSIX constructions
      [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
      5.6 and 5.8 do. */

      if (c == CHAR_LEFT_SQUARE_BRACKET &&
          (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
           ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr))
        {
        BOOL local_negate = FALSE;
        int posix_class, taboffset, tabopt;
        register const pcre_uint8 *cbits = cd->cbits;
        pcre_uint8 pbits[32];

        if (ptr[1] != CHAR_COLON)
          {
          *errorcodeptr = ERR31;
          goto FAILED;
          }

        ptr += 2;
        if (*ptr == CHAR_CIRCUMFLEX_ACCENT)
          {
          local_negate = TRUE;
          should_flip_negation = TRUE;  /* Note negative special */
          ptr++;
          }

        posix_class = check_posix_name(ptr, (int)(tempptr - ptr));
        if (posix_class < 0)
          {
          *errorcodeptr = ERR30;
          goto FAILED;
          }

        /* If matching is caseless, upper and lower are converted to
        alpha. This relies on the fact that the class table starts with
        alpha, lower, upper as the first 3 entries. */

        if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
          posix_class = 0;

        /* When PCRE_UCP is set, some of the POSIX classes are converted to
        different escape sequences that use Unicode properties. */

#ifdef SUPPORT_UCP
        if ((options & PCRE_UCP) != 0)
          {
          int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0);
          if (posix_substitutes[pc] != NULL)
            {
            nestptr = tempptr + 1;
            ptr = posix_substitutes[pc] - 1;
            continue;
            }
          }
#endif
        /* In the non-UCP case, we build the bit map for the POSIX class in a
        chunk of local store because we may be adding and subtracting from it,
        and we don't want to subtract bits that may be in the main map already.
        At the end we or the result into the bit map that is being built. */

        posix_class *= 3;

        /* Copy in the first table (always present) */

        memcpy(pbits, cbits + posix_class_maps[posix_class],
          32 * sizeof(pcre_uint8));

        /* If there is a second table, add or remove it as required. */

        taboffset = posix_class_maps[posix_class + 1];
        tabopt = posix_class_maps[posix_class + 2];

        if (taboffset >= 0)
          {
          if (tabopt >= 0)
            for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset];
          else
            for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset];
          }

        /* Not see if we need to remove any special characters. An option
        value of 1 removes vertical space and 2 removes underscore. */

        if (tabopt < 0) tabopt = -tabopt;
        if (tabopt == 1) pbits[1] &= ~0x3c;
          else if (tabopt == 2) pbits[11] &= 0x7f;

        /* Add the POSIX table or its complement into the main table that is
        being built and we are done. */

        if (local_negate)
          for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c];
        else
          for (c = 0; c < 32; c++) classbits[c] |= pbits[c];

        ptr = tempptr + 1;
        /* Every class contains at least one < 256 characters. */
        class_has_8bitchar = 1;
        /* Every class contains at least two characters. */
        class_single_char = 2;
        continue;    /* End of POSIX syntax handling */
        }

      /* Backslash may introduce a single character, or it may introduce one
      of the specials, which just set a flag. The sequence \b is a special
      case. Inside a class (and only there) it is treated as backspace. We
      assume that other escapes have more than one character in them, so
      speculatively set both class_has_8bitchar and class_single_char bigger
      than one. Unrecognized escapes fall through and are either treated
      as literal characters (by default), or are faulted if
      PCRE_EXTRA is set. */

      if (c == CHAR_BACKSLASH)
        {
        c = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
        if (*errorcodeptr != 0) goto FAILED;

        if (-c == ESC_b) c = CHAR_BS;    /* \b is backspace in a class */
        else if (-c == ESC_N)            /* \N is not supported in a class */
          {
          *errorcodeptr = ERR71;
          goto FAILED;
          }
        else if (-c == ESC_Q)            /* Handle start of quoted string */
          {
          if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
            {
            ptr += 2; /* avoid empty string */
            }
          else inescq = TRUE;
          continue;
          }
        else if (-c == ESC_E) continue;  /* Ignore orphan \E */

        if (c < 0)
          {
          register const pcre_uint8 *cbits = cd->cbits;
          /* Every class contains at least two < 256 characters. */
          class_has_8bitchar++;
          /* Every class contains at least two characters. */
          class_single_char += 2;

          switch (-c)
            {
#ifdef SUPPORT_UCP
            case ESC_du:     /* These are the values given for \d etc */
            case ESC_DU:     /* when PCRE_UCP is set. We replace the */
            case ESC_wu:     /* escape sequence with an appropriate \p */
            case ESC_WU:     /* or \P to test Unicode properties instead */
            case ESC_su:     /* of the default ASCII testing. */
            case ESC_SU:
            nestptr = ptr;
            ptr = substitutes[-c - ESC_DU] - 1;  /* Just before substitute */
            class_has_8bitchar--;                /* Undo! */
            continue;
#endif
            case ESC_d:
            for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
            continue;

            case ESC_D:
            should_flip_negation = TRUE;
            for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit];
            continue;

            case ESC_w:
            for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word];
            continue;

            case ESC_W:
            should_flip_negation = TRUE;
            for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word];
            continue;

            /* Perl 5.004 onwards omits VT from \s, but we must preserve it
            if it was previously set by something earlier in the character
            class. */

            case ESC_s:
            classbits[0] |= cbits[cbit_space];
            classbits[1] |= cbits[cbit_space+1] & ~0x08;
            for (c = 2; c < 32; c++) classbits[c] |= cbits[c+cbit_space];
            continue;

            case ESC_S:
            should_flip_negation = TRUE;
            for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space];
            classbits[1] |= 0x08;    /* Perl 5.004 onwards omits VT from \s */
            continue;

            case ESC_h:
            SETBIT(classbits, 0x09); /* VT */
            SETBIT(classbits, 0x20); /* SPACE */
            SETBIT(classbits, 0xa0); /* NSBP */
#ifndef COMPILE_PCRE8
            xclass = TRUE;
            *class_uchardata++ = XCL_SINGLE;
            *class_uchardata++ = 0x1680;
            *class_uchardata++ = XCL_SINGLE;
            *class_uchardata++ = 0x180e;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x2000;
            *class_uchardata++ = 0x200a;
            *class_uchardata++ = XCL_SINGLE;
            *class_uchardata++ = 0x202f;
            *class_uchardata++ = XCL_SINGLE;
            *class_uchardata++ = 0x205f;
            *class_uchardata++ = XCL_SINGLE;
            *class_uchardata++ = 0x3000;
#elif defined SUPPORT_UTF
            if (utf)
              {
              xclass = TRUE;
              *class_uchardata++ = XCL_SINGLE;
              class_uchardata += PRIV(ord2utf)(0x1680, class_uchardata);
              *class_uchardata++ = XCL_SINGLE;
              class_uchardata += PRIV(ord2utf)(0x180e, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x2000, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x200a, class_uchardata);
              *class_uchardata++ = XCL_SINGLE;
              class_uchardata += PRIV(ord2utf)(0x202f, class_uchardata);
              *class_uchardata++ = XCL_SINGLE;
              class_uchardata += PRIV(ord2utf)(0x205f, class_uchardata);
              *class_uchardata++ = XCL_SINGLE;
              class_uchardata += PRIV(ord2utf)(0x3000, class_uchardata);
              }
#endif
            continue;

            case ESC_H:
            for (c = 0; c < 32; c++)
              {
              int x = 0xff;
              switch (c)
                {
                case 0x09/8: x = 1 << (0x09%8); break;
                case 0x20/8: x = 1 << (0x20%8); break;
                case 0xa0/8: x = 1 << (0xa0%8); break;
                default: break;
                }
              classbits[c] |= x;
              }
#ifndef COMPILE_PCRE8
            xclass = TRUE;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x0100;
            *class_uchardata++ = 0x167f;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x1681;
            *class_uchardata++ = 0x180d;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x180f;
            *class_uchardata++ = 0x1fff;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x200b;
            *class_uchardata++ = 0x202e;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x2030;
            *class_uchardata++ = 0x205e;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x2060;
            *class_uchardata++ = 0x2fff;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x3001;
#ifdef SUPPORT_UTF
            if (utf)
              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
            else
#endif
              *class_uchardata++ = 0xffff;
#elif defined SUPPORT_UTF
            if (utf)
              {
              xclass = TRUE;
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x167f, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x1681, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x180d, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x180f, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x1fff, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x200b, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x202e, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x2030, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x205e, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x2060, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x2fff, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x3001, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
              }
#endif
            continue;

            case ESC_v:
            SETBIT(classbits, 0x0a); /* LF */
            SETBIT(classbits, 0x0b); /* VT */
            SETBIT(classbits, 0x0c); /* FF */
            SETBIT(classbits, 0x0d); /* CR */
            SETBIT(classbits, 0x85); /* NEL */
#ifndef COMPILE_PCRE8
            xclass = TRUE;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x2028;
            *class_uchardata++ = 0x2029;
#elif defined SUPPORT_UTF
            if (utf)
              {
              xclass = TRUE;
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x2028, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x2029, class_uchardata);
              }
#endif
            continue;

            case ESC_V:
            for (c = 0; c < 32; c++)
              {
              int x = 0xff;
              switch (c)
                {
                case 0x0a/8: x = 1 << (0x0a%8);
                             x = 1 << (0x0b%8);
                             x = 1 << (0x0c%8);
                             x = 1 << (0x0d%8);
                             break;
                case 0x85/8: x = 1 << (0x85%8); break;
                default: break;
                }
              classbits[c] |= x;
              }

#ifndef COMPILE_PCRE8
            xclass = TRUE;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x0100;
            *class_uchardata++ = 0x2027;
            *class_uchardata++ = XCL_RANGE;
            *class_uchardata++ = 0x202a;
#ifdef SUPPORT_UTF
            if (utf)
              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
            else
#endif
              *class_uchardata++ = 0xffff;
#elif defined SUPPORT_UTF
            if (utf)
              {
              xclass = TRUE;
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x2027, class_uchardata);
              *class_uchardata++ = XCL_RANGE;
              class_uchardata += PRIV(ord2utf)(0x202a, class_uchardata);
              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
              }
#endif
            continue;

#ifdef SUPPORT_UCP
            case ESC_p:
            case ESC_P:
              {
              BOOL negated;
              int pdata;
              int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
              if (ptype < 0) goto FAILED;
              xclass = TRUE;
              *class_uchardata++ = ((-c == ESC_p) != negated)?
                XCL_PROP : XCL_NOTPROP;
              *class_uchardata++ = ptype;
              *class_uchardata++ = pdata;
              class_has_8bitchar--;                /* Undo! */
              continue;
              }
#endif
            /* Unrecognized escapes are faulted if PCRE is running in its
            strict mode. By default, for compatibility with Perl, they are
            treated as literals. */

            default:
            if ((options & PCRE_EXTRA) != 0)
              {
              *errorcodeptr = ERR7;
              goto FAILED;
              }
            class_has_8bitchar--;    /* Undo the speculative increase. */
            class_single_char -= 2;  /* Undo the speculative increase. */
            c = *ptr;                /* Get the final character and fall through */
            break;
            }
          }

        /* Fall through if we have a single character (c >= 0). This may be
        greater than 256. */

        }   /* End of backslash handling */

      /* A single character may be followed by '-' to form a range. However,
      Perl does not permit ']' to be the end of the range. A '-' character
      at the end is treated as a literal. Perl ignores orphaned \E sequences
      entirely. The code for handling \Q and \E is messy. */

      CHECK_RANGE:
      while (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
        {
        inescq = FALSE;
        ptr += 2;
        }

      oldptr = ptr;

      /* Remember \r or \n */

      if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;

      /* Check for range */

      if (!inescq && ptr[1] == CHAR_MINUS)
        {
        int d;
        ptr += 2;
        while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2;

        /* If we hit \Q (not followed by \E) at this point, go into escaped
        mode. */

        while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
          {
          ptr += 2;
          if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E)
            { ptr += 2; continue; }
          inescq = TRUE;
          break;
          }

        if (*ptr == 0 || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET))
          {
          ptr = oldptr;
          goto LONE_SINGLE_CHARACTER;
          }

#ifdef SUPPORT_UTF
        if (utf)
          {                           /* Braces are required because the */
          GETCHARLEN(d, ptr, ptr);    /* macro generates multiple statements */
          }
        else
#endif
        d = *ptr;  /* Not UTF-8 mode */

        /* The second part of a range can be a single-character escape, but
        not any of the other escapes. Perl 5.6 treats a hyphen as a literal
        in such circumstances. */

        if (!inescq && d == CHAR_BACKSLASH)
          {
          d = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
          if (*errorcodeptr != 0) goto FAILED;

          /* \b is backspace; any other special means the '-' was literal */

          if (d < 0)
            {
            if (d == -ESC_b) d = CHAR_BS; else
              {
              ptr = oldptr;
              goto LONE_SINGLE_CHARACTER;  /* A few lines below */
              }
            }
          }

        /* Check that the two values are in the correct order. Optimize
        one-character ranges */

        if (d < c)
          {
          *errorcodeptr = ERR8;
          goto FAILED;
          }

        if (d == c) goto LONE_SINGLE_CHARACTER;  /* A few lines below */

        /* Remember \r or \n */

        if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;

        /* Since we found a character range, single character optimizations
        cannot be done anymore. */
        class_single_char = 2;

        /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless
        matching, we have to use an XCLASS with extra data items. Caseless
        matching for characters > 127 is available only if UCP support is
        available. */

#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8)
        if ((d > 255) || (utf && ((options & PCRE_CASELESS) != 0 && d > 127)))
#elif defined  SUPPORT_UTF
        if (utf && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127)))
#elif !(defined COMPILE_PCRE8)
        if (d > 255)
#endif
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
          {
          xclass = TRUE;

          /* With UCP support, we can find the other case equivalents of
          the relevant characters. There may be several ranges. Optimize how
          they fit with the basic range. */

#ifdef SUPPORT_UCP
#ifndef COMPILE_PCRE8
          if (utf && (options & PCRE_CASELESS) != 0)
#else
          if ((options & PCRE_CASELESS) != 0)
#endif
            {
            unsigned int occ, ocd;
            unsigned int cc = c;
            unsigned int origd = d;
            while (get_othercase_range(&cc, origd, &occ, &ocd))
              {
              if (occ >= (unsigned int)c &&
                  ocd <= (unsigned int)d)
                continue;                          /* Skip embedded ranges */

              if (occ < (unsigned int)c  &&
                  ocd >= (unsigned int)c - 1)      /* Extend the basic range */
                {                                  /* if there is overlap,   */
                c = occ;                           /* noting that if occ < c */
                continue;                          /* we can't have ocd > d  */
                }                                  /* because a subrange is  */
              if (ocd > (unsigned int)d &&
                  occ <= (unsigned int)d + 1)      /* always shorter than    */
                {                                  /* the basic range.       */
                d = ocd;
                continue;
                }

              if (occ == ocd)
                {
                *class_uchardata++ = XCL_SINGLE;
                }
              else
                {
                *class_uchardata++ = XCL_RANGE;
                class_uchardata += PRIV(ord2utf)(occ, class_uchardata);
                }
              class_uchardata += PRIV(ord2utf)(ocd, class_uchardata);
              }
            }
#endif  /* SUPPORT_UCP */

          /* Now record the original range, possibly modified for UCP caseless
          overlapping ranges. */

          *class_uchardata++ = XCL_RANGE;
#ifdef SUPPORT_UTF
#ifndef COMPILE_PCRE8
          if (utf)
            {
            class_uchardata += PRIV(ord2utf)(c, class_uchardata);
            class_uchardata += PRIV(ord2utf)(d, class_uchardata);
            }
          else
            {
            *class_uchardata++ = c;
            *class_uchardata++ = d;
            }
#else
          class_uchardata += PRIV(ord2utf)(c, class_uchardata);
          class_uchardata += PRIV(ord2utf)(d, class_uchardata);
#endif
#else /* SUPPORT_UTF */
          *class_uchardata++ = c;
          *class_uchardata++ = d;
#endif /* SUPPORT_UTF */

          /* With UCP support, we are done. Without UCP support, there is no
          caseless matching for UTF characters > 127; we can use the bit map
          for the smaller ones. As for 16 bit characters without UTF, we
          can still use  */

#ifdef SUPPORT_UCP
#ifndef COMPILE_PCRE8
          if (utf)
#endif
            continue;    /* With next character in the class */
#endif  /* SUPPORT_UCP */

#if defined SUPPORT_UTF && !defined(SUPPORT_UCP) && !(defined COMPILE_PCRE8)
          if (utf)
            {
            if ((options & PCRE_CASELESS) == 0 || c > 127) continue;
            /* Adjust upper limit and fall through to set up the map */
            d = 127;
            }
          else
            {
            if (c > 255) continue;
            /* Adjust upper limit and fall through to set up the map */
            d = 255;
            }
#elif defined SUPPORT_UTF && !defined(SUPPORT_UCP)
          if ((options & PCRE_CASELESS) == 0 || c > 127) continue;
          /* Adjust upper limit and fall through to set up the map */
          d = 127;
#else
          if (c > 255) continue;
          /* Adjust upper limit and fall through to set up the map */
          d = 255;
#endif  /* SUPPORT_UTF && !SUPPORT_UCP && !COMPILE_PCRE8 */
          }
#endif  /* SUPPORT_UTF || !COMPILE_PCRE8 */

        /* We use the bit map for 8 bit mode, or when the characters fall
        partially or entirely to [0-255] ([0-127] for UCP) ranges. */

        class_has_8bitchar = 1;

        /* We can save a bit of time by skipping this in the pre-compile. */

        if (lengthptr == NULL) for (; c <= d; c++)
          {
          classbits[c/8] |= (1 << (c&7));
          if ((options & PCRE_CASELESS) != 0)
            {
            int uc = cd->fcc[c]; /* flip case */
            classbits[uc/8] |= (1 << (uc&7));
            }
          }

        continue;   /* Go get the next char in the class */
        }

      /* Handle a lone single character - we can get here for a normal
      non-escape char, or after \ that introduces a single character or for an
      apparent range that isn't. */

      LONE_SINGLE_CHARACTER:

      /* Only the value of 1 matters for class_single_char. */

      if (class_single_char < 2) class_single_char++;

      /* If class_charcount is 1, we saw precisely one character. As long as
      there was no use of \p or \P, in other words, no use of any XCLASS
      features, we can optimize.

      The optimization throws away the bit map. We turn the item into a
      1-character OP_CHAR[I] if it's positive, or OP_NOT[I] if it's negative.
      In the positive case, it can cause firstchar to be set. Otherwise, there
      can be no first char if this item is first, whatever repeat count may
      follow. In the case of reqchar, save the previous value for reinstating. */

      if (class_single_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
        {
        ptr++;
        zeroreqchar = reqchar;

        if (negate_class)
          {
          if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
          zerofirstchar = firstchar;
          *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT;
#ifdef SUPPORT_UTF
          if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
            code += PRIV(ord2utf)(c, code);
          else
#endif
            *code++ = c;
          goto NOT_CHAR;
          }

        /* For a single, positive character, get the value into mcbuffer, and
        then we can handle this with the normal one-character code. */

#ifdef SUPPORT_UTF
        if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
          mclength = PRIV(ord2utf)(c, mcbuffer);
        else
#endif
          {
          mcbuffer[0] = c;
          mclength = 1;
          }
        goto ONE_CHAR;
        }       /* End of 1-char optimization */

      /* Handle a character that cannot go in the bit map. */

#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8)
      if ((c > 255) || (utf && ((options & PCRE_CASELESS) != 0 && c > 127)))
#elif defined SUPPORT_UTF
      if (utf && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127)))
#elif !(defined COMPILE_PCRE8)
      if (c > 255)
#endif

#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
        {
        xclass = TRUE;
        *class_uchardata++ = XCL_SINGLE;
#ifdef SUPPORT_UTF
#ifndef COMPILE_PCRE8
        /* In non 8 bit mode, we can get here even if we are not in UTF mode. */
        if (!utf)
          *class_uchardata++ = c;
        else
#endif
          class_uchardata += PRIV(ord2utf)(c, class_uchardata);
#else /* SUPPORT_UTF */
        *class_uchardata++ = c;
#endif /* SUPPORT_UTF */

#ifdef SUPPORT_UCP
#ifdef COMPILE_PCRE8
        if ((options & PCRE_CASELESS) != 0)
#else
        /* In non 8 bit mode, we can get here even if we are not in UTF mode. */
        if (utf && (options & PCRE_CASELESS) != 0)
#endif
          {
          unsigned int othercase;
          if ((int)(othercase = UCD_OTHERCASE(c)) != c)
            {
            *class_uchardata++ = XCL_SINGLE;
            class_uchardata += PRIV(ord2utf)(othercase, class_uchardata);
            }
          }
#endif  /* SUPPORT_UCP */

        }
      else
#endif  /* SUPPORT_UTF || COMPILE_PCRE16 */

      /* Handle a single-byte character */
        {
        class_has_8bitchar = 1;
        classbits[c/8] |= (1 << (c&7));
        if ((options & PCRE_CASELESS) != 0)
          {
          c = cd->fcc[c]; /* flip case */
          classbits[c/8] |= (1 << (c&7));
          }
        }
      }

    /* Loop until ']' reached. This "while" is the end of the "do" far above.
    If we are at the end of an internal nested string, revert to the outer
    string. */

    while (((c = *(++ptr)) != 0 ||
           (nestptr != NULL &&
             (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != 0)) &&
           (c != CHAR_RIGHT_SQUARE_BRACKET || inescq));

    /* Check for missing terminating ']' */

    if (c == 0)
      {
      *errorcodeptr = ERR6;
      goto FAILED;
      }

    /* If this is the first thing in the branch, there can be no first char
    setting, whatever the repeat count. Any reqchar setting must remain
    unchanged after any kind of repeat. */

    if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
    zerofirstchar = firstchar;
    zeroreqchar = reqchar;

    /* If there are characters with values > 255, we have to compile an
    extended class, with its own opcode, unless there was a negated special
    such as \S in the class, and PCRE_UCP is not set, because in that case all
    characters > 255 are in the class, so any that were explicitly given as
    well can be ignored. If (when there are explicit characters > 255 that must
    be listed) there are no characters < 256, we can omit the bitmap in the
    actual compiled code. */

#ifdef SUPPORT_UTF
    if (xclass && (!should_flip_negation || (options & PCRE_UCP) != 0))
#elif !defined COMPILE_PCRE8
    if (xclass && !should_flip_negation)
#endif
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
      {
      *class_uchardata++ = XCL_END;    /* Marks the end of extra data */
      *code++ = OP_XCLASS;
      code += LINK_SIZE;
      *code = negate_class? XCL_NOT:0;

      /* If the map is required, move up the extra data to make room for it;
      otherwise just move the code pointer to the end of the extra data. */

      if (class_has_8bitchar > 0)
        {
        *code++ |= XCL_MAP;
        memmove(code + (32 / sizeof(pcre_uchar)), code,
          IN_UCHARS(class_uchardata - code));
        memcpy(code, classbits, 32);
        code = class_uchardata + (32 / sizeof(pcre_uchar));
        }
      else code = class_uchardata;

      /* Now fill in the complete length of the item */

      PUT(previous, 1, (int)(code - previous));
      break;   /* End of class handling */
      }
#endif

    /* If there are no characters > 255, or they are all to be included or
    excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the
    whole class was negated and whether there were negative specials such as \S
    (non-UCP) in the class. Then copy the 32-byte map into the code vector,
    negating it if necessary. */

    *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;
    if (lengthptr == NULL)    /* Save time in the pre-compile phase */
      {
      if (negate_class)
        for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
      memcpy(code, classbits, 32);
      }
    code += 32 / sizeof(pcre_uchar);
    NOT_CHAR:
    break;


    /* ===================================================================*/
    /* Various kinds of repeat; '{' is not necessarily a quantifier, but this
    has been tested above. */

    case CHAR_LEFT_CURLY_BRACKET:
    if (!is_quantifier) goto NORMAL_CHAR;
    ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr);
    if (*errorcodeptr != 0) goto FAILED;
    goto REPEAT;

    case CHAR_ASTERISK:
    repeat_min = 0;
    repeat_max = -1;
    goto REPEAT;

    case CHAR_PLUS:
    repeat_min = 1;
    repeat_max = -1;
    goto REPEAT;

    case CHAR_QUESTION_MARK:
    repeat_min = 0;
    repeat_max = 1;

    REPEAT:
    if (previous == NULL)
      {
      *errorcodeptr = ERR9;
      goto FAILED;
      }

    if (repeat_min == 0)
      {
      firstchar = zerofirstchar;    /* Adjust for zero repeat */
      reqchar = zeroreqchar;        /* Ditto */
      }

    /* Remember whether this is a variable length repeat */

    reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;

    op_type = 0;                    /* Default single-char op codes */
    possessive_quantifier = FALSE;  /* Default not possessive quantifier */

    /* Save start of previous item, in case we have to move it up in order to
    insert something before it. */

    tempcode = previous;

    /* If the next character is '+', we have a possessive quantifier. This
    implies greediness, whatever the setting of the PCRE_UNGREEDY option.
    If the next character is '?' this is a minimizing repeat, by default,
    but if PCRE_UNGREEDY is set, it works the other way round. We change the
    repeat type to the non-default. */

    if (ptr[1] == CHAR_PLUS)
      {
      repeat_type = 0;                  /* Force greedy */
      possessive_quantifier = TRUE;
      ptr++;
      }
    else if (ptr[1] == CHAR_QUESTION_MARK)
      {
      repeat_type = greedy_non_default;
      ptr++;
      }
    else repeat_type = greedy_default;

    /* If previous was a recursion call, wrap it in atomic brackets so that
    previous becomes the atomic group. All recursions were so wrapped in the
    past, but it no longer happens for non-repeated recursions. In fact, the
    repeated ones could be re-implemented independently so as not to need this,
    but for the moment we rely on the code for repeating groups. */

    if (*previous == OP_RECURSE)
      {
      memmove(previous + 1 + LINK_SIZE, previous, IN_UCHARS(1 + LINK_SIZE));
      *previous = OP_ONCE;
      PUT(previous, 1, 2 + 2*LINK_SIZE);
      previous[2 + 2*LINK_SIZE] = OP_KET;
      PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE);
      code += 2 + 2 * LINK_SIZE;
      length_prevgroup = 3 + 3*LINK_SIZE;

      /* When actually compiling, we need to check whether this was a forward
      reference, and if so, adjust the offset. */

      if (lengthptr == NULL && cd->hwm >= cd->start_workspace + LINK_SIZE)
        {
        int offset = GET(cd->hwm, -LINK_SIZE);
        if (offset == previous + 1 - cd->start_code)
          PUT(cd->hwm, -LINK_SIZE, offset + 1 + LINK_SIZE);
        }
      }

    /* Now handle repetition for the different types of item. */

    /* If previous was a character or negated character match, abolish the item
    and generate a repeat item instead. If a char item has a minimum of more
    than one, ensure that it is set in reqchar - it might not be if a sequence
    such as x{3} is the first thing in a branch because the x will have gone
    into firstchar instead.  */

    if (*previous == OP_CHAR || *previous == OP_CHARI
        || *previous == OP_NOT || *previous == OP_NOTI)
      {
      switch (*previous)
        {
        default: /* Make compiler happy. */
        case OP_CHAR:  op_type = OP_STAR - OP_STAR; break;
        case OP_CHARI: op_type = OP_STARI - OP_STAR; break;
        case OP_NOT:   op_type = OP_NOTSTAR - OP_STAR; break;
        case OP_NOTI:  op_type = OP_NOTSTARI - OP_STAR; break;
        }

      /* Deal with UTF characters that take up more than one character. It's
      easier to write this out separately than try to macrify it. Use c to
      hold the length of the character in bytes, plus UTF_LENGTH to flag that
      it's a length rather than a small character. */

#ifdef SUPPORT_UTF
      if (utf && NOT_FIRSTCHAR(code[-1]))
        {
        pcre_uchar *lastchar = code - 1;
        BACKCHAR(lastchar);
        c = (int)(code - lastchar);     /* Length of UTF-8 character */
        memcpy(utf_chars, lastchar, IN_UCHARS(c)); /* Save the char */
        c |= UTF_LENGTH;                /* Flag c as a length */
        }
      else
#endif /* SUPPORT_UTF */

      /* Handle the case of a single charater - either with no UTF support, or
      with UTF disabled, or for a single character UTF character. */
        {
        c = code[-1];
        if (*previous <= OP_CHARI && repeat_min > 1)
          reqchar = c | req_caseopt | cd->req_varyopt;
        }

      /* If the repetition is unlimited, it pays to see if the next thing on
      the line is something that cannot possibly match this character. If so,
      automatically possessifying this item gains some performance in the case
      where the match fails. */

      if (!possessive_quantifier &&
          repeat_max < 0 &&
          check_auto_possessive(previous, utf, ptr + 1, options, cd))
        {
        repeat_type = 0;    /* Force greedy */
        possessive_quantifier = TRUE;
        }

      goto OUTPUT_SINGLE_REPEAT;   /* Code shared with single character types */
      }

    /* If previous was a character type match (\d or similar), abolish it and
    create a suitable repeat item. The code is shared with single-character
    repeats by setting op_type to add a suitable offset into repeat_type. Note
    the the Unicode property types will be present only when SUPPORT_UCP is
    defined, but we don't wrap the little bits of code here because it just
    makes it horribly messy. */

    else if (*previous < OP_EODN)
      {
      pcre_uchar *oldcode;
      int prop_type, prop_value;
      op_type = OP_TYPESTAR - OP_STAR;  /* Use type opcodes */
      c = *previous;

      if (!possessive_quantifier &&
          repeat_max < 0 &&
          check_auto_possessive(previous, utf, ptr + 1, options, cd))
        {
        repeat_type = 0;    /* Force greedy */
        possessive_quantifier = TRUE;
        }

      OUTPUT_SINGLE_REPEAT:
      if (*previous == OP_PROP || *previous == OP_NOTPROP)
        {
        prop_type = previous[1];
        prop_value = previous[2];
        }
      else prop_type = prop_value = -1;

      oldcode = code;
      code = previous;                  /* Usually overwrite previous item */

      /* If the maximum is zero then the minimum must also be zero; Perl allows
      this case, so we do too - by simply omitting the item altogether. */

      if (repeat_max == 0) goto END_REPEAT;

      /*--------------------------------------------------------------------*/
      /* This code is obsolete from release 8.00; the restriction was finally
      removed: */

      /* All real repeats make it impossible to handle partial matching (maybe
      one day we will be able to remove this restriction). */

      /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */
      /*--------------------------------------------------------------------*/

      /* Combine the op_type with the repeat_type */

      repeat_type += op_type;

      /* A minimum of zero is handled either as the special case * or ?, or as
      an UPTO, with the maximum given. */

      if (repeat_min == 0)
        {
        if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
          else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
        else
          {
          *code++ = OP_UPTO + repeat_type;
          PUT2INC(code, 0, repeat_max);
          }
        }

      /* A repeat minimum of 1 is optimized into some special cases. If the
      maximum is unlimited, we use OP_PLUS. Otherwise, the original item is
      left in place and, if the maximum is greater than 1, we use OP_UPTO with
      one less than the maximum. */

      else if (repeat_min == 1)
        {
        if (repeat_max == -1)
          *code++ = OP_PLUS + repeat_type;
        else
          {
          code = oldcode;                 /* leave previous item in place */
          if (repeat_max == 1) goto END_REPEAT;
          *code++ = OP_UPTO + repeat_type;
          PUT2INC(code, 0, repeat_max - 1);
          }
        }

      /* The case {n,n} is just an EXACT, while the general case {n,m} is
      handled as an EXACT followed by an UPTO. */

      else
        {
        *code++ = OP_EXACT + op_type;  /* NB EXACT doesn't have repeat_type */
        PUT2INC(code, 0, repeat_min);

        /* If the maximum is unlimited, insert an OP_STAR. Before doing so,
        we have to insert the character for the previous code. For a repeated
        Unicode property match, there are two extra bytes that define the
        required property. In UTF-8 mode, long characters have their length in
        c, with the UTF_LENGTH bit as a flag. */

        if (repeat_max < 0)
          {
#ifdef SUPPORT_UTF
          if (utf && (c & UTF_LENGTH) != 0)
            {
            memcpy(code, utf_chars, IN_UCHARS(c & 7));
            code += c & 7;
            }
          else
#endif
            {
            *code++ = c;
            if (prop_type >= 0)
              {
              *code++ = prop_type;
              *code++ = prop_value;
              }
            }
          *code++ = OP_STAR + repeat_type;
          }

        /* Else insert an UPTO if the max is greater than the min, again
        preceded by the character, for the previously inserted code. If the
        UPTO is just for 1 instance, we can use QUERY instead. */

        else if (repeat_max != repeat_min)
          {
#ifdef SUPPORT_UTF
          if (utf && (c & UTF_LENGTH) != 0)
            {
            memcpy(code, utf_chars, IN_UCHARS(c & 7));
            code += c & 7;
            }
          else
#endif
          *code++ = c;
          if (prop_type >= 0)
            {
            *code++ = prop_type;
            *code++ = prop_value;
            }
          repeat_max -= repeat_min;

          if (repeat_max == 1)
            {
            *code++ = OP_QUERY + repeat_type;
            }
          else
            {
            *code++ = OP_UPTO + repeat_type;
            PUT2INC(code, 0, repeat_max);
            }
          }
        }

      /* The character or character type itself comes last in all cases. */

#ifdef SUPPORT_UTF
      if (utf && (c & UTF_LENGTH) != 0)
        {
        memcpy(code, utf_chars, IN_UCHARS(c & 7));
        code += c & 7;
        }
      else
#endif
      *code++ = c;

      /* For a repeated Unicode property match, there are two extra bytes that
      define the required property. */

#ifdef SUPPORT_UCP
      if (prop_type >= 0)
        {
        *code++ = prop_type;
        *code++ = prop_value;
        }
#endif
      }

    /* If previous was a character class or a back reference, we put the repeat
    stuff after it, but just skip the item if the repeat was {0,0}. */

    else if (*previous == OP_CLASS ||
             *previous == OP_NCLASS ||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
             *previous == OP_XCLASS ||
#endif
             *previous == OP_REF ||
             *previous == OP_REFI)
      {
      if (repeat_max == 0)
        {
        code = previous;
        goto END_REPEAT;
        }

      /*--------------------------------------------------------------------*/
      /* This code is obsolete from release 8.00; the restriction was finally
      removed: */

      /* All real repeats make it impossible to handle partial matching (maybe
      one day we will be able to remove this restriction). */

      /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */
      /*--------------------------------------------------------------------*/

      if (repeat_min == 0 && repeat_max == -1)
        *code++ = OP_CRSTAR + repeat_type;
      else if (repeat_min == 1 && repeat_max == -1)
        *code++ = OP_CRPLUS + repeat_type;
      else if (repeat_min == 0 && repeat_max == 1)
        *code++ = OP_CRQUERY + repeat_type;
      else
        {
        *code++ = OP_CRRANGE + repeat_type;
        PUT2INC(code, 0, repeat_min);
        if (repeat_max == -1) repeat_max = 0;  /* 2-byte encoding for max */
        PUT2INC(code, 0, repeat_max);
        }
      }

    /* If previous was a bracket group, we may have to replicate it in certain
    cases. Note that at this point we can encounter only the "basic" bracket
    opcodes such as BRA and CBRA, as this is the place where they get converted
    into the more special varieties such as BRAPOS and SBRA. A test for >=
    OP_ASSERT and <= OP_COND includes ASSERT, ASSERT_NOT, ASSERTBACK,
    ASSERTBACK_NOT, ONCE, BRA, CBRA, and COND. Originally, PCRE did not allow
    repetition of assertions, but now it does, for Perl compatibility. */

    else if (*previous >= OP_ASSERT && *previous <= OP_COND)
      {
      register int i;
      int len = (int)(code - previous);
      pcre_uchar *bralink = NULL;
      pcre_uchar *brazeroptr = NULL;

      /* Repeating a DEFINE group is pointless, but Perl allows the syntax, so
      we just ignore the repeat. */

      if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF)
        goto END_REPEAT;

      /* There is no sense in actually repeating assertions. The only potential
      use of repetition is in cases when the assertion is optional. Therefore,
      if the minimum is greater than zero, just ignore the repeat. If the
      maximum is not not zero or one, set it to 1. */

      if (*previous < OP_ONCE)    /* Assertion */
        {
        if (repeat_min > 0) goto END_REPEAT;
        if (repeat_max < 0 || repeat_max > 1) repeat_max = 1;
        }

      /* The case of a zero minimum is special because of the need to stick
      OP_BRAZERO in front of it, and because the group appears once in the
      data, whereas in other cases it appears the minimum number of times. For
      this reason, it is simplest to treat this case separately, as otherwise
      the code gets far too messy. There are several special subcases when the
      minimum is zero. */

      if (repeat_min == 0)
        {
        /* If the maximum is also zero, we used to just omit the group from the
        output altogether, like this:

        ** if (repeat_max == 0)
        **   {
        **   code = previous;
        **   goto END_REPEAT;
        **   }

        However, that fails when a group or a subgroup within it is referenced
        as a subroutine from elsewhere in the pattern, so now we stick in
        OP_SKIPZERO in front of it so that it is skipped on execution. As we
        don't have a list of which groups are referenced, we cannot do this
        selectively.

        If the maximum is 1 or unlimited, we just have to stick in the BRAZERO
        and do no more at this point. However, we do need to adjust any
        OP_RECURSE calls inside the group that refer to the group itself or any
        internal or forward referenced group, because the offset is from the
        start of the whole regex. Temporarily terminate the pattern while doing
        this. */

        if (repeat_max <= 1)    /* Covers 0, 1, and unlimited */
          {
          *code = OP_END;
          adjust_recurse(previous, 1, utf, cd, save_hwm);
          memmove(previous + 1, previous, IN_UCHARS(len));
          code++;
          if (repeat_max == 0)
            {
            *previous++ = OP_SKIPZERO;
            goto END_REPEAT;
            }
          brazeroptr = previous;    /* Save for possessive optimizing */
          *previous++ = OP_BRAZERO + repeat_type;
          }

        /* If the maximum is greater than 1 and limited, we have to replicate
        in a nested fashion, sticking OP_BRAZERO before each set of brackets.
        The first one has to be handled carefully because it's the original
        copy, which has to be moved up. The remainder can be handled by code
        that is common with the non-zero minimum case below. We have to
        adjust the value or repeat_max, since one less copy is required. Once
        again, we may have to adjust any OP_RECURSE calls inside the group. */

        else
          {
          int offset;
          *code = OP_END;
          adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm);
          memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
          code += 2 + LINK_SIZE;
          *previous++ = OP_BRAZERO + repeat_type;
          *previous++ = OP_BRA;

          /* We chain together the bracket offset fields that have to be
          filled in later when the ends of the brackets are reached. */

          offset = (bralink == NULL)? 0 : (int)(previous - bralink);
          bralink = previous;
          PUTINC(previous, 0, offset);
          }

        repeat_max--;
        }

      /* If the minimum is greater than zero, replicate the group as many
      times as necessary, and adjust the maximum to the number of subsequent
      copies that we need. If we set a first char from the group, and didn't
      set a required char, copy the latter from the former. If there are any
      forward reference subroutine calls in the group, there will be entries on
      the workspace list; replicate these with an appropriate increment. */

      else
        {
        if (repeat_min > 1)
          {
          /* In the pre-compile phase, we don't actually do the replication. We
          just adjust the length as if we had. Do some paranoid checks for
          potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit
          integer type when available, otherwise double. */

          if (lengthptr != NULL)
            {
            int delta = (repeat_min - 1)*length_prevgroup;
            if ((INT64_OR_DOUBLE)(repeat_min - 1)*
                  (INT64_OR_DOUBLE)length_prevgroup >
                    (INT64_OR_DOUBLE)INT_MAX ||
                OFLOW_MAX - *lengthptr < delta)
              {
              *errorcodeptr = ERR20;
              goto FAILED;
              }
            *lengthptr += delta;
            }

          /* This is compiling for real. If there is a set first byte for
          the group, and we have not yet set a "required byte", set it. Make
          sure there is enough workspace for copying forward references before
          doing the copy. */

          else
            {
            if (groupsetfirstchar && reqchar < 0) reqchar = firstchar;

            for (i = 1; i < repeat_min; i++)
              {
              pcre_uchar *hc;
              pcre_uchar *this_hwm = cd->hwm;
              memcpy(code, previous, IN_UCHARS(len));

              while (cd->hwm > cd->start_workspace + cd->workspace_size -
                     WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
                {
                int save_offset = save_hwm - cd->start_workspace;
                int this_offset = this_hwm - cd->start_workspace;
                *errorcodeptr = expand_workspace(cd);
                if (*errorcodeptr != 0) goto FAILED;
                save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
                this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
                }

              for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
                {
                PUT(cd->hwm, 0, GET(hc, 0) + len);
                cd->hwm += LINK_SIZE;
                }
              save_hwm = this_hwm;
              code += len;
              }
            }
          }

        if (repeat_max > 0) repeat_max -= repeat_min;
        }

      /* This code is common to both the zero and non-zero minimum cases. If
      the maximum is limited, it replicates the group in a nested fashion,
      remembering the bracket starts on a stack. In the case of a zero minimum,
      the first one was set up above. In all cases the repeat_max now specifies
      the number of additional copies needed. Again, we must remember to
      replicate entries on the forward reference list. */

      if (repeat_max >= 0)
        {
        /* In the pre-compile phase, we don't actually do the replication. We
        just adjust the length as if we had. For each repetition we must add 1
        to the length for BRAZERO and for all but the last repetition we must
        add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some
        paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type is
        a 64-bit integer type when available, otherwise double. */

        if (lengthptr != NULL && repeat_max > 0)
          {
          int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) -
                      2 - 2*LINK_SIZE;   /* Last one doesn't nest */
          if ((INT64_OR_DOUBLE)repeat_max *
                (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE)
                  > (INT64_OR_DOUBLE)INT_MAX ||
              OFLOW_MAX - *lengthptr < delta)
            {
            *errorcodeptr = ERR20;
            goto FAILED;
            }
          *lengthptr += delta;
          }

        /* This is compiling for real */

        else for (i = repeat_max - 1; i >= 0; i--)
          {
          pcre_uchar *hc;
          pcre_uchar *this_hwm = cd->hwm;

          *code++ = OP_BRAZERO + repeat_type;

          /* All but the final copy start a new nesting, maintaining the
          chain of brackets outstanding. */

          if (i != 0)
            {
            int offset;
            *code++ = OP_BRA;
            offset = (bralink == NULL)? 0 : (int)(code - bralink);
            bralink = code;
            PUTINC(code, 0, offset);
            }

          memcpy(code, previous, IN_UCHARS(len));

          /* Ensure there is enough workspace for forward references before
          copying them. */

          while (cd->hwm > cd->start_workspace + cd->workspace_size -
                 WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
            {
            int save_offset = save_hwm - cd->start_workspace;
            int this_offset = this_hwm - cd->start_workspace;
            *errorcodeptr = expand_workspace(cd);
            if (*errorcodeptr != 0) goto FAILED;
            save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
            this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
            }

          for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
            {
            PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
            cd->hwm += LINK_SIZE;
            }
          save_hwm = this_hwm;
          code += len;
          }

        /* Now chain through the pending brackets, and fill in their length
        fields (which are holding the chain links pro tem). */

        while (bralink != NULL)
          {
          int oldlinkoffset;
          int offset = (int)(code - bralink + 1);
          pcre_uchar *bra = code - offset;
          oldlinkoffset = GET(bra, 1);
          bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
          *code++ = OP_KET;
          PUTINC(code, 0, offset);
          PUT(bra, 1, offset);
          }
        }

      /* If the maximum is unlimited, set a repeater in the final copy. For
      ONCE brackets, that's all we need to do. However, possessively repeated
      ONCE brackets can be converted into non-capturing brackets, as the
      behaviour of (?:xx)++ is the same as (?>xx)++ and this saves having to
      deal with possessive ONCEs specially.

      Otherwise, when we are doing the actual compile phase, check to see
      whether this group is one that could match an empty string. If so,
      convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so
      that runtime checking can be done. [This check is also applied to ONCE
      groups at runtime, but in a different way.]

      Then, if the quantifier was possessive and the bracket is not a
      conditional, we convert the BRA code to the POS form, and the KET code to
      KETRPOS. (It turns out to be convenient at runtime to detect this kind of
      subpattern at both the start and at the end.) The use of special opcodes
      makes it possible to reduce greatly the stack usage in PCREXEC8(). If
      the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO.

      Then, if the minimum number of matches is 1 or 0, cancel the possessive
      flag so that the default action below, of wrapping everything inside
      atomic brackets, does not happen. When the minimum is greater than 1,
      there will be earlier copies of the group, and so we still have to wrap
      the whole thing. */

      else
        {
        pcre_uchar *ketcode = code - 1 - LINK_SIZE;
        pcre_uchar *bracode = ketcode - GET(ketcode, 1);

        /* Convert possessive ONCE brackets to non-capturing */

        if ((*bracode == OP_ONCE || *bracode == OP_ONCE_NC) &&
            possessive_quantifier) *bracode = OP_BRA;

        /* For non-possessive ONCE brackets, all we need to do is to
        set the KET. */

        if (*bracode == OP_ONCE || *bracode == OP_ONCE_NC)
          *ketcode = OP_KETRMAX + repeat_type;

        /* Handle non-ONCE brackets and possessive ONCEs (which have been
        converted to non-capturing above). */

        else
          {
          /* In the compile phase, check for empty string matching. */

          if (lengthptr == NULL)
            {
            pcre_uchar *scode = bracode;
            do
              {
              if (could_be_empty_branch(scode, ketcode, utf, cd))
                {
                *bracode += OP_SBRA - OP_BRA;
                break;
                }
              scode += GET(scode, 1);
              }
            while (*scode == OP_ALT);
            }

          /* Handle possessive quantifiers. */

          if (possessive_quantifier)
            {
            /* For COND brackets, we wrap the whole thing in a possessively
            repeated non-capturing bracket, because we have not invented POS
            versions of the COND opcodes. Because we are moving code along, we
            must ensure that any pending recursive references are updated. */

            if (*bracode == OP_COND || *bracode == OP_SCOND)
              {
              int nlen = (int)(code - bracode);
              *code = OP_END;
              adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm);
              memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
              code += 1 + LINK_SIZE;
              nlen += 1 + LINK_SIZE;
              *bracode = OP_BRAPOS;
              *code++ = OP_KETRPOS;
              PUTINC(code, 0, nlen);
              PUT(bracode, 1, nlen);
              }

            /* For non-COND brackets, we modify the BRA code and use KETRPOS. */

            else
              {
              *bracode += 1;              /* Switch to xxxPOS opcodes */
              *ketcode = OP_KETRPOS;
              }

            /* If the minimum is zero, mark it as possessive, then unset the
            possessive flag when the minimum is 0 or 1. */

            if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO;
            if (repeat_min < 2) possessive_quantifier = FALSE;
            }

          /* Non-possessive quantifier */

          else *ketcode = OP_KETRMAX + repeat_type;
          }
        }
      }

    /* If previous is OP_FAIL, it was generated by an empty class [] in
    JavaScript mode. The other ways in which OP_FAIL can be generated, that is
    by (*FAIL) or (?!) set previous to NULL, which gives a "nothing to repeat"
    error above. We can just ignore the repeat in JS case. */

    else if (*previous == OP_FAIL) goto END_REPEAT;

    /* Else there's some kind of shambles */

    else
      {
      *errorcodeptr = ERR11;
      goto FAILED;
      }

    /* If the character following a repeat is '+', or if certain optimization
    tests above succeeded, possessive_quantifier is TRUE. For some opcodes,
    there are special alternative opcodes for this case. For anything else, we
    wrap the entire repeated item inside OP_ONCE brackets. Logically, the '+'
    notation is just syntactic sugar, taken from Sun's Java package, but the
    special opcodes can optimize it.

    Some (but not all) possessively repeated subpatterns have already been
    completely handled in the code just above. For them, possessive_quantifier
    is always FALSE at this stage.

    Note that the repeated item starts at tempcode, not at previous, which
    might be the first part of a string whose (former) last char we repeated.

    Possessifying an 'exact' quantifier has no effect, so we can ignore it. But
    an 'upto' may follow. We skip over an 'exact' item, and then test the
    length of what remains before proceeding. */

    if (possessive_quantifier)
      {
      int len;

      if (*tempcode == OP_TYPEEXACT)
        tempcode += PRIV(OP_lengths)[*tempcode] +
          ((tempcode[1 + IMM2_SIZE] == OP_PROP
          || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);

      else if (*tempcode == OP_EXACT || *tempcode == OP_NOTEXACT)
        {
        tempcode += PRIV(OP_lengths)[*tempcode];
#ifdef SUPPORT_UTF
        if (utf && HAS_EXTRALEN(tempcode[-1]))
          tempcode += GET_EXTRALEN(tempcode[-1]);
#endif
        }

      len = (int)(code - tempcode);
      if (len > 0) switch (*tempcode)
        {
        case OP_STAR:  *tempcode = OP_POSSTAR; break;
        case OP_PLUS:  *tempcode = OP_POSPLUS; break;
        case OP_QUERY: *tempcode = OP_POSQUERY; break;
        case OP_UPTO:  *tempcode = OP_POSUPTO; break;

        case OP_STARI:  *tempcode = OP_POSSTARI; break;
        case OP_PLUSI:  *tempcode = OP_POSPLUSI; break;
        case OP_QUERYI: *tempcode = OP_POSQUERYI; break;
        case OP_UPTOI:  *tempcode = OP_POSUPTOI; break;

        case OP_NOTSTAR:  *tempcode = OP_NOTPOSSTAR; break;
        case OP_NOTPLUS:  *tempcode = OP_NOTPOSPLUS; break;
        case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break;
        case OP_NOTUPTO:  *tempcode = OP_NOTPOSUPTO; break;

        case OP_NOTSTARI:  *tempcode = OP_NOTPOSSTARI; break;
        case OP_NOTPLUSI:  *tempcode = OP_NOTPOSPLUSI; break;
        case OP_NOTQUERYI: *tempcode = OP_NOTPOSQUERYI; break;
        case OP_NOTUPTOI:  *tempcode = OP_NOTPOSUPTOI; break;

        case OP_TYPESTAR:  *tempcode = OP_TYPEPOSSTAR; break;
        case OP_TYPEPLUS:  *tempcode = OP_TYPEPOSPLUS; break;
        case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break;
        case OP_TYPEUPTO:  *tempcode = OP_TYPEPOSUPTO; break;

        /* Because we are moving code along, we must ensure that any
        pending recursive references are updated. */

        default:
        *code = OP_END;
        adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
        memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
        code += 1 + LINK_SIZE;
        len += 1 + LINK_SIZE;
        tempcode[0] = OP_ONCE;
        *code++ = OP_KET;
        PUTINC(code, 0, len);
        PUT(tempcode, 1, len);
        break;
        }
      }

    /* In all case we no longer have a previous item. We also set the
    "follows varying string" flag for subsequently encountered reqchars if
    it isn't already set and we have just passed a varying length item. */

    END_REPEAT:
    previous = NULL;
    cd->req_varyopt |= reqvary;
    break;


    /* ===================================================================*/
    /* Start of nested parenthesized sub-expression, or comment or lookahead or
    lookbehind or option setting or condition or all the other extended
    parenthesis forms.  */

    case CHAR_LEFT_PARENTHESIS:
    newoptions = options;
    skipbytes = 0;
    bravalue = OP_CBRA;
    save_hwm = cd->hwm;
    reset_bracount = FALSE;

    /* First deal with various "verbs" that can be introduced by '*'. */

    ptr++;
    if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
         || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0))))
      {
      int i, namelen;
      int arglen = 0;
      const char *vn = verbnames;
      const pcre_uchar *name = ptr + 1;
      const pcre_uchar *arg = NULL;
      previous = NULL;
      ptr++;
      while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
      namelen = (int)(ptr - name);

      /* It appears that Perl allows any characters whatsoever, other than
      a closing parenthesis, to appear in arguments, so we no longer insist on
      letters, digits, and underscores. */

      if (*ptr == CHAR_COLON)
        {
        arg = ++ptr;
        while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
        arglen = (int)(ptr - arg);
        if (arglen > (int)MAX_MARK)
          {
          *errorcodeptr = ERR75;
          goto FAILED;
          }
        }

      if (*ptr != CHAR_RIGHT_PARENTHESIS)
        {
        *errorcodeptr = ERR60;
        goto FAILED;
        }

      /* Scan the table of verb names */

      for (i = 0; i < verbcount; i++)
        {
        if (namelen == verbs[i].len &&
            STRNCMP_UC_C8(name, vn, namelen) == 0)
          {
          /* Check for open captures before ACCEPT and convert it to
          ASSERT_ACCEPT if in an assertion. */

          if (verbs[i].op == OP_ACCEPT)
            {
            open_capitem *oc;
            if (arglen != 0)
              {
              *errorcodeptr = ERR59;
              goto FAILED;
              }
            cd->had_accept = TRUE;
            for (oc = cd->open_caps; oc != NULL; oc = oc->next)
              {
              *code++ = OP_CLOSE;
              PUT2INC(code, 0, oc->number);
              }
            *code++ = (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;

            /* Do not set firstchar after *ACCEPT */
            if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
            }

          /* Handle other cases with/without an argument */

          else if (arglen == 0)
            {
            if (verbs[i].op < 0)   /* Argument is mandatory */
              {
              *errorcodeptr = ERR66;
              goto FAILED;
              }
            *code = verbs[i].op;
            if (*code++ == OP_THEN) cd->external_flags |= PCRE_HASTHEN;
            }

          else
            {
            if (verbs[i].op_arg < 0)   /* Argument is forbidden */
              {
              *errorcodeptr = ERR59;
              goto FAILED;
              }
            *code = verbs[i].op_arg;
            if (*code++ == OP_THEN_ARG) cd->external_flags |= PCRE_HASTHEN;
            *code++ = arglen;
            memcpy(code, arg, IN_UCHARS(arglen));
            code += arglen;
            *code++ = 0;
            }

          break;  /* Found verb, exit loop */
          }

        vn += verbs[i].len + 1;
        }

      if (i < verbcount) continue;    /* Successfully handled a verb */
      *errorcodeptr = ERR60;          /* Verb not recognized */
      goto FAILED;
      }

    /* Deal with the extended parentheses; all are introduced by '?', and the
    appearance of any of them means that this is not a capturing group. */

    else if (*ptr == CHAR_QUESTION_MARK)
      {
      int i, set, unset, namelen;
      int *optset;
      const pcre_uchar *name;
      pcre_uchar *slot;

      switch (*(++ptr))
        {
        case CHAR_NUMBER_SIGN:                 /* Comment; skip to ket */
        ptr++;
        while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
        if (*ptr == 0)
          {
          *errorcodeptr = ERR18;
          goto FAILED;
          }
        continue;


        /* ------------------------------------------------------------ */
        case CHAR_VERTICAL_LINE:  /* Reset capture count for each branch */
        reset_bracount = TRUE;
        /* Fall through */

        /* ------------------------------------------------------------ */
        case CHAR_COLON:          /* Non-capturing bracket */
        bravalue = OP_BRA;
        ptr++;
        break;


        /* ------------------------------------------------------------ */
        case CHAR_LEFT_PARENTHESIS:
        bravalue = OP_COND;       /* Conditional group */

        /* A condition can be an assertion, a number (referring to a numbered
        group), a name (referring to a named group), or 'R', referring to
        recursion. R<digits> and R&name are also permitted for recursion tests.

        There are several syntaxes for testing a named group: (?(name)) is used
        by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).

        There are two unfortunate ambiguities, caused by history. (a) 'R' can
        be the recursive thing or the name 'R' (and similarly for 'R' followed
        by digits), and (b) a number could be a name that consists of digits.
        In both cases, we look for a name first; if not found, we try the other
        cases. */

        /* For conditions that are assertions, check the syntax, and then exit
        the switch. This will take control down to where bracketed groups,
        including assertions, are processed. */

        if (ptr[1] == CHAR_QUESTION_MARK && (ptr[2] == CHAR_EQUALS_SIGN ||
            ptr[2] == CHAR_EXCLAMATION_MARK || ptr[2] == CHAR_LESS_THAN_SIGN))
          break;

        /* Most other conditions use OP_CREF (a couple change to OP_RREF
        below), and all need to skip 1+IMM2_SIZE bytes at the start of the group. */

        code[1+LINK_SIZE] = OP_CREF;
        skipbytes = 1+IMM2_SIZE;
        refsign = -1;

        /* Check for a test for recursion in a named group. */

        if (ptr[1] == CHAR_R && ptr[2] == CHAR_AMPERSAND)
          {
          terminator = -1;
          ptr += 2;
          code[1+LINK_SIZE] = OP_RREF;    /* Change the type of test */
          }

        /* Check for a test for a named group's having been set, using the Perl
        syntax (?(<name>) or (?('name') */

        else if (ptr[1] == CHAR_LESS_THAN_SIGN)
          {
          terminator = CHAR_GREATER_THAN_SIGN;
          ptr++;
          }
        else if (ptr[1] == CHAR_APOSTROPHE)
          {
          terminator = CHAR_APOSTROPHE;
          ptr++;
          }
        else
          {
          terminator = 0;
          if (ptr[1] == CHAR_MINUS || ptr[1] == CHAR_PLUS) refsign = *(++ptr);
          }

        /* We now expect to read a name; any thing else is an error */

        if (!MAX_255(ptr[1]) || (cd->ctypes[ptr[1]] & ctype_word) == 0)
          {
          ptr += 1;  /* To get the right offset */
          *errorcodeptr = ERR28;
          goto FAILED;
          }

        /* Read the name, but also get it as a number if it's all digits */

        recno = 0;
        name = ++ptr;
        while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0)
          {
          if (recno >= 0)
            recno = (IS_DIGIT(*ptr))? recno * 10 + *ptr - CHAR_0 : -1;
          ptr++;
          }
        namelen = (int)(ptr - name);

        if ((terminator > 0 && *ptr++ != terminator) ||
            *ptr++ != CHAR_RIGHT_PARENTHESIS)
          {
          ptr--;      /* Error offset */
          *errorcodeptr = ERR26;
          goto FAILED;
          }

        /* Do no further checking in the pre-compile phase. */

        if (lengthptr != NULL) break;

        /* In the real compile we do the work of looking for the actual
        reference. If the string started with "+" or "-" we require the rest to
        be digits, in which case recno will be set. */

        if (refsign > 0)
          {
          if (recno <= 0)
            {
            *errorcodeptr = ERR58;
            goto FAILED;
            }
          recno = (refsign == CHAR_MINUS)?
            cd->bracount - recno + 1 : recno +cd->bracount;
          if (recno <= 0 || recno > cd->final_bracount)
            {
            *errorcodeptr = ERR15;
            goto FAILED;
            }
          PUT2(code, 2+LINK_SIZE, recno);
          break;
          }

        /* Otherwise (did not start with "+" or "-"), start by looking for the
        name. If we find a name, add one to the opcode to change OP_CREF or
        OP_RREF into OP_NCREF or OP_NRREF. These behave exactly the same,
        except they record that the reference was originally to a name. The
        information is used to check duplicate names. */

        slot = cd->name_table;
        for (i = 0; i < cd->names_found; i++)
          {
          if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break;
          slot += cd->name_entry_size;
          }

        /* Found a previous named subpattern */

        if (i < cd->names_found)
          {
          recno = GET2(slot, 0);
          PUT2(code, 2+LINK_SIZE, recno);
          code[1+LINK_SIZE]++;
          }

        /* Search the pattern for a forward reference */

        else if ((i = find_parens(cd, name, namelen,
                        (options & PCRE_EXTENDED) != 0, utf)) > 0)
          {
          PUT2(code, 2+LINK_SIZE, i);
          code[1+LINK_SIZE]++;
          }

        /* If terminator == 0 it means that the name followed directly after
        the opening parenthesis [e.g. (?(abc)...] and in this case there are
        some further alternatives to try. For the cases where terminator != 0
        [things like (?(<name>... or (?('name')... or (?(R&name)... ] we have
        now checked all the possibilities, so give an error. */

        else if (terminator != 0)
          {
          *errorcodeptr = ERR15;
          goto FAILED;
          }

        /* Check for (?(R) for recursion. Allow digits after R to specify a
        specific group number. */

        else if (*name == CHAR_R)
          {
          recno = 0;
          for (i = 1; i < namelen; i++)
            {
            if (!IS_DIGIT(name[i]))
              {
              *errorcodeptr = ERR15;
              goto FAILED;
              }
            recno = recno * 10 + name[i] - CHAR_0;
            }
          if (recno == 0) recno = RREF_ANY;
          code[1+LINK_SIZE] = OP_RREF;      /* Change test type */
          PUT2(code, 2+LINK_SIZE, recno);
          }

        /* Similarly, check for the (?(DEFINE) "condition", which is always
        false. */

        else if (namelen == 6 && STRNCMP_UC_C8(name, STRING_DEFINE, 6) == 0)
          {
          code[1+LINK_SIZE] = OP_DEF;
          skipbytes = 1;
          }

        /* Check for the "name" actually being a subpattern number. We are
        in the second pass here, so final_bracount is set. */

        else if (recno > 0 && recno <= cd->final_bracount)
          {
          PUT2(code, 2+LINK_SIZE, recno);
          }

        /* Either an unidentified subpattern, or a reference to (?(0) */

        else
          {
          *errorcodeptr = (recno == 0)? ERR35: ERR15;
          goto FAILED;
          }
        break;


        /* ------------------------------------------------------------ */
        case CHAR_EQUALS_SIGN:                 /* Positive lookahead */
        bravalue = OP_ASSERT;
        cd->assert_depth += 1;
        ptr++;
        break;


        /* ------------------------------------------------------------ */
        case CHAR_EXCLAMATION_MARK:            /* Negative lookahead */
        ptr++;
        if (*ptr == CHAR_RIGHT_PARENTHESIS)    /* Optimize (?!) */
          {
          *code++ = OP_FAIL;
          previous = NULL;
          continue;
          }
        bravalue = OP_ASSERT_NOT;
        cd->assert_depth += 1;
        break;


        /* ------------------------------------------------------------ */
        case CHAR_LESS_THAN_SIGN:              /* Lookbehind or named define */
        switch (ptr[1])
          {
          case CHAR_EQUALS_SIGN:               /* Positive lookbehind */
          bravalue = OP_ASSERTBACK;
          cd->assert_depth += 1;
          ptr += 2;
          break;

          case CHAR_EXCLAMATION_MARK:          /* Negative lookbehind */
          bravalue = OP_ASSERTBACK_NOT;
          cd->assert_depth += 1;
          ptr += 2;
          break;

          default:                /* Could be name define, else bad */
          if (MAX_255(ptr[1]) && (cd->ctypes[ptr[1]] & ctype_word) != 0)
            goto DEFINE_NAME;
          ptr++;                  /* Correct offset for error */
          *errorcodeptr = ERR24;
          goto FAILED;
          }
        break;


        /* ------------------------------------------------------------ */
        case CHAR_GREATER_THAN_SIGN:           /* One-time brackets */
        bravalue = OP_ONCE;
        ptr++;
        break;


        /* ------------------------------------------------------------ */
        case CHAR_C:                 /* Callout - may be followed by digits; */
        previous_callout = code;     /* Save for later completion */
        after_manual_callout = 1;    /* Skip one item before completing */
        *code++ = OP_CALLOUT;
          {
          int n = 0;
          ptr++;
          while(IS_DIGIT(*ptr))
            n = n * 10 + *ptr++ - CHAR_0;
          if (*ptr != CHAR_RIGHT_PARENTHESIS)
            {
            *errorcodeptr = ERR39;
            goto FAILED;
            }
          if (n > 255)
            {
            *errorcodeptr = ERR38;
            goto FAILED;
            }
          *code++ = n;
          PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */
          PUT(code, LINK_SIZE, 0);                          /* Default length */
          code += 2 * LINK_SIZE;
          }
        previous = NULL;
        continue;


        /* ------------------------------------------------------------ */
        case CHAR_P:              /* Python-style named subpattern handling */
        if (*(++ptr) == CHAR_EQUALS_SIGN ||
            *ptr == CHAR_GREATER_THAN_SIGN)  /* Reference or recursion */
          {
          is_recurse = *ptr == CHAR_GREATER_THAN_SIGN;
          terminator = CHAR_RIGHT_PARENTHESIS;
          goto NAMED_REF_OR_RECURSE;
          }
        else if (*ptr != CHAR_LESS_THAN_SIGN)  /* Test for Python-style defn */
          {
          *errorcodeptr = ERR41;
          goto FAILED;
          }
        /* Fall through to handle (?P< as (?< is handled */


        /* ------------------------------------------------------------ */
        DEFINE_NAME:    /* Come here from (?< handling */
        case CHAR_APOSTROPHE:
          {
          terminator = (*ptr == CHAR_LESS_THAN_SIGN)?
            CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
          name = ++ptr;

          while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
          namelen = (int)(ptr - name);

          /* In the pre-compile phase, just do a syntax check. */

          if (lengthptr != NULL)
            {
            if (*ptr != terminator)
              {
              *errorcodeptr = ERR42;
              goto FAILED;
              }
            if (cd->names_found >= MAX_NAME_COUNT)
              {
              *errorcodeptr = ERR49;
              goto FAILED;
              }
            if (namelen + IMM2_SIZE + 1 > cd->name_entry_size)
              {
              cd->name_entry_size = namelen + IMM2_SIZE + 1;
              if (namelen > MAX_NAME_SIZE)
                {
                *errorcodeptr = ERR48;
                goto FAILED;
                }
              }
            }

          /* In the real compile, create the entry in the table, maintaining
          alphabetical order. Duplicate names for different numbers are
          permitted only if PCRE_DUPNAMES is set. Duplicate names for the same
          number are always OK. (An existing number can be re-used if (?|
          appears in the pattern.) In either event, a duplicate name results in
          a duplicate entry in the table, even if the number is the same. This
          is because the number of names, and hence the table size, is computed
          in the pre-compile, and it affects various numbers and pointers which
          would all have to be modified, and the compiled code moved down, if
          duplicates with the same number were omitted from the table. This
          doesn't seem worth the hassle. However, *different* names for the
          same number are not permitted. */

          else
            {
            BOOL dupname = FALSE;
            slot = cd->name_table;

            for (i = 0; i < cd->names_found; i++)
              {
              int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(namelen));
              if (crc == 0)
                {
                if (slot[IMM2_SIZE+namelen] == 0)
                  {
                  if (GET2(slot, 0) != cd->bracount + 1 &&
                      (options & PCRE_DUPNAMES) == 0)
                    {
                    *errorcodeptr = ERR43;
                    goto FAILED;
                    }
                  else dupname = TRUE;
                  }
                else crc = -1;      /* Current name is a substring */
                }

              /* Make space in the table and break the loop for an earlier
              name. For a duplicate or later name, carry on. We do this for
              duplicates so that in the simple case (when ?(| is not used) they
              are in order of their numbers. */

              if (crc < 0)
                {
                memmove(slot + cd->name_entry_size, slot,
                  IN_UCHARS((cd->names_found - i) * cd->name_entry_size));
                break;
                }

              /* Continue the loop for a later or duplicate name */

              slot += cd->name_entry_size;
              }

            /* For non-duplicate names, check for a duplicate number before
            adding the new name. */

            if (!dupname)
              {
              pcre_uchar *cslot = cd->name_table;
              for (i = 0; i < cd->names_found; i++)
                {
                if (cslot != slot)
                  {
                  if (GET2(cslot, 0) == cd->bracount + 1)
                    {
                    *errorcodeptr = ERR65;
                    goto FAILED;
                    }
                  }
                else i--;
                cslot += cd->name_entry_size;
                }
              }

            PUT2(slot, 0, cd->bracount + 1);
            memcpy(slot + IMM2_SIZE, name, IN_UCHARS(namelen));
            slot[IMM2_SIZE + namelen] = 0;
            }
          }

        /* In both pre-compile and compile, count the number of names we've
        encountered. */

        cd->names_found++;
        ptr++;                    /* Move past > or ' */
        goto NUMBERED_GROUP;


        /* ------------------------------------------------------------ */
        case CHAR_AMPERSAND:            /* Perl recursion/subroutine syntax */
        terminator = CHAR_RIGHT_PARENTHESIS;
        is_recurse = TRUE;
        /* Fall through */

        /* We come here from the Python syntax above that handles both
        references (?P=name) and recursion (?P>name), as well as falling
        through from the Perl recursion syntax (?&name). We also come here from
        the Perl \k<name> or \k'name' back reference syntax and the \k{name}
        .NET syntax, and the Oniguruma \g<...> and \g'...' subroutine syntax. */

        NAMED_REF_OR_RECURSE:
        name = ++ptr;
        while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
        namelen = (int)(ptr - name);

        /* In the pre-compile phase, do a syntax check. We used to just set
        a dummy reference number, because it was not used in the first pass.
        However, with the change of recursive back references to be atomic,
        we have to look for the number so that this state can be identified, as
        otherwise the incorrect length is computed. If it's not a backwards
        reference, the dummy number will do. */

        if (lengthptr != NULL)
          {
          const pcre_uchar *temp;

          if (namelen == 0)
            {
            *errorcodeptr = ERR62;
            goto FAILED;
            }
          if (*ptr != terminator)
            {
            *errorcodeptr = ERR42;
            goto FAILED;
            }
          if (namelen > MAX_NAME_SIZE)
            {
            *errorcodeptr = ERR48;
            goto FAILED;
            }

          /* The name table does not exist in the first pass, so we cannot
          do a simple search as in the code below. Instead, we have to scan the
          pattern to find the number. It is important that we scan it only as
          far as we have got because the syntax of named subpatterns has not
          been checked for the rest of the pattern, and find_parens() assumes
          correct syntax. In any case, it's a waste of resources to scan
          further. We stop the scan at the current point by temporarily
          adjusting the value of cd->endpattern. */

          temp = cd->end_pattern;
          cd->end_pattern = ptr;
          recno = find_parens(cd, name, namelen,
            (options & PCRE_EXTENDED) != 0, utf);
          cd->end_pattern = temp;
          if (recno < 0) recno = 0;    /* Forward ref; set dummy number */
          }

        /* In the real compile, seek the name in the table. We check the name
        first, and then check that we have reached the end of the name in the
        table. That way, if the name that is longer than any in the table,
        the comparison will fail without reading beyond the table entry. */

        else
          {
          slot = cd->name_table;
          for (i = 0; i < cd->names_found; i++)
            {
            if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 &&
                slot[IMM2_SIZE+namelen] == 0)
              break;
            slot += cd->name_entry_size;
            }

          if (i < cd->names_found)         /* Back reference */
            {
            recno = GET2(slot, 0);
            }
          else if ((recno =                /* Forward back reference */
                    find_parens(cd, name, namelen,
                      (options & PCRE_EXTENDED) != 0, utf)) <= 0)
            {
            *errorcodeptr = ERR15;
            goto FAILED;
            }
          }

        /* In both phases, we can now go to the code than handles numerical
        recursion or backreferences. */

        if (is_recurse) goto HANDLE_RECURSION;
          else goto HANDLE_REFERENCE;


        /* ------------------------------------------------------------ */
        case CHAR_R:              /* Recursion */
        ptr++;                    /* Same as (?0)      */
        /* Fall through */


        /* ------------------------------------------------------------ */
        case CHAR_MINUS: case CHAR_PLUS:  /* Recursion or subroutine */
        case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4:
        case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:
          {
          const pcre_uchar *called;
          terminator = CHAR_RIGHT_PARENTHESIS;

          /* Come here from the \g<...> and \g'...' code (Oniguruma
          compatibility). However, the syntax has been checked to ensure that
          the ... are a (signed) number, so that neither ERR63 nor ERR29 will
          be called on this path, nor with the jump to OTHER_CHAR_AFTER_QUERY
          ever be taken. */

          HANDLE_NUMERICAL_RECURSION:

          if ((refsign = *ptr) == CHAR_PLUS)
            {
            ptr++;
            if (!IS_DIGIT(*ptr))
              {
              *errorcodeptr = ERR63;
              goto FAILED;
              }
            }
          else if (refsign == CHAR_MINUS)
            {
            if (!IS_DIGIT(ptr[1]))
              goto OTHER_CHAR_AFTER_QUERY;
            ptr++;
            }

          recno = 0;
          while(IS_DIGIT(*ptr))
            recno = recno * 10 + *ptr++ - CHAR_0;

          if (*ptr != terminator)
            {
            *errorcodeptr = ERR29;
            goto FAILED;
            }

          if (refsign == CHAR_MINUS)
            {
            if (recno == 0)
              {
              *errorcodeptr = ERR58;
              goto FAILED;
              }
            recno = cd->bracount - recno + 1;
            if (recno <= 0)
              {
              *errorcodeptr = ERR15;
              goto FAILED;
              }
            }
          else if (refsign == CHAR_PLUS)
            {
            if (recno == 0)
              {
              *errorcodeptr = ERR58;
              goto FAILED;
              }
            recno += cd->bracount;
            }

          /* Come here from code above that handles a named recursion */

          HANDLE_RECURSION:

          previous = code;
          called = cd->start_code;

          /* When we are actually compiling, find the bracket that is being
          referenced. Temporarily end the regex in case it doesn't exist before
          this point. If we end up with a forward reference, first check that
          the bracket does occur later so we can give the error (and position)
          now. Then remember this forward reference in the workspace so it can
          be filled in at the end. */

          if (lengthptr == NULL)
            {
            *code = OP_END;
            if (recno != 0)
              called = PRIV(find_bracket)(cd->start_code, utf, recno);

            /* Forward reference */

            if (called == NULL)
              {
              if (find_parens(cd, NULL, recno,
                    (options & PCRE_EXTENDED) != 0, utf) < 0)
                {
                *errorcodeptr = ERR15;
                goto FAILED;
                }

              /* Fudge the value of "called" so that when it is inserted as an
              offset below, what it actually inserted is the reference number
              of the group. Then remember the forward reference. */

              called = cd->start_code + recno;
              if (cd->hwm >= cd->start_workspace + cd->workspace_size -
                  WORK_SIZE_SAFETY_MARGIN)
                {
                *errorcodeptr = expand_workspace(cd);
                if (*errorcodeptr != 0) goto FAILED;
                }
              PUTINC(cd->hwm, 0, (int)(code + 1 - cd->start_code));
              }

            /* If not a forward reference, and the subpattern is still open,
            this is a recursive call. We check to see if this is a left
            recursion that could loop for ever, and diagnose that case. We
            must not, however, do this check if we are in a conditional
            subpattern because the condition might be testing for recursion in
            a pattern such as /(?(R)a+|(?R)b)/, which is perfectly valid.
            Forever loops are also detected at runtime, so those that occur in
            conditional subpatterns will be picked up then. */

            else if (GET(called, 1) == 0 && cond_depth <= 0 &&
                     could_be_empty(called, code, bcptr, utf, cd))
              {
              *errorcodeptr = ERR40;
              goto FAILED;
              }
            }

          /* Insert the recursion/subroutine item. It does not have a set first
          character (relevant if it is repeated, because it will then be
          wrapped with ONCE brackets). */

          *code = OP_RECURSE;
          PUT(code, 1, (int)(called - cd->start_code));
          code += 1 + LINK_SIZE;
          groupsetfirstchar = FALSE;
          }

        /* Can't determine a first byte now */

        if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
        continue;


        /* ------------------------------------------------------------ */
        default:              /* Other characters: check option setting */
        OTHER_CHAR_AFTER_QUERY:
        set = unset = 0;
        optset = &set;

        while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON)
          {
          switch (*ptr++)
            {
            case CHAR_MINUS: optset = &unset; break;

            case CHAR_J:    /* Record that it changed in the external options */
            *optset |= PCRE_DUPNAMES;
            cd->external_flags |= PCRE_JCHANGED;
            break;

            case CHAR_i: *optset |= PCRE_CASELESS; break;
            case CHAR_m: *optset |= PCRE_MULTILINE; break;
            case CHAR_s: *optset |= PCRE_DOTALL; break;
            case CHAR_x: *optset |= PCRE_EXTENDED; break;
            case CHAR_U: *optset |= PCRE_UNGREEDY; break;
            case CHAR_X: *optset |= PCRE_EXTRA; break;

            default:  *errorcodeptr = ERR12;
                      ptr--;    /* Correct the offset */
                      goto FAILED;
            }
          }

        /* Set up the changed option bits, but don't change anything yet. */

        newoptions = (options | set) & (~unset);

        /* If the options ended with ')' this is not the start of a nested
        group with option changes, so the options change at this level. If this
        item is right at the start of the pattern, the options can be
        abstracted and made external in the pre-compile phase, and ignored in
        the compile phase. This can be helpful when matching -- for instance in
        caseless checking of required bytes.

        If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are
        definitely *not* at the start of the pattern because something has been
        compiled. In the pre-compile phase, however, the code pointer can have
        that value after the start, because it gets reset as code is discarded
        during the pre-compile. However, this can happen only at top level - if
        we are within parentheses, the starting BRA will still be present. At
        any parenthesis level, the length value can be used to test if anything
        has been compiled at that level. Thus, a test for both these conditions
        is necessary to ensure we correctly detect the start of the pattern in
        both phases.

        If we are not at the pattern start, reset the greedy defaults and the
        case value for firstchar and reqchar. */

        if (*ptr == CHAR_RIGHT_PARENTHESIS)
          {
          if (code == cd->start_code + 1 + LINK_SIZE &&
               (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE))
            {
            cd->external_options = newoptions;
            }
          else
            {
            greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
            greedy_non_default = greedy_default  1;
            req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
            }

          /* Change options at this level, and pass them back for use
          in subsequent branches. */

          *optionsptr = options = newoptions;
          previous = NULL;       /* This item can't be repeated */
          continue;              /* It is complete */
          }

        /* If the options ended with ':' we are heading into a nested group
        with possible change of options. Such groups are non-capturing and are
        not assertions of any kind. All we need to do is skip over the ':';
        the newoptions value is handled below. */

        bravalue = OP_BRA;
        ptr++;
        }     /* End of switch for character following (? */
      }       /* End of (? handling */

    /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE
    is set, all unadorned brackets become non-capturing and behave like (?:...)
    brackets. */

    else if ((options & PCRE_NO_AUTO_CAPTURE) != 0)
      {
      bravalue = OP_BRA;
      }

    /* Else we have a capturing group. */

    else
      {
      NUMBERED_GROUP:
      cd->bracount += 1;
      PUT2(code, 1+LINK_SIZE, cd->bracount);
      skipbytes = IMM2_SIZE;
      }

    /* Process nested bracketed regex. Assertions used not to be repeatable,
    but this was changed for Perl compatibility, so all kinds can now be
    repeated. We copy code into a non-register variable (tempcode) in order to
    be able to pass its address because some compilers complain otherwise. */

    previous = code;                      /* For handling repetition */
    *code = bravalue;
    tempcode = code;
    tempreqvary = cd->req_varyopt;        /* Save value before bracket */
    tempbracount = cd->bracount;          /* Save value before bracket */
    length_prevgroup = 0;                 /* Initialize for pre-compile phase */

    if (!compile_regex(
         newoptions,                      /* The complete new option state */
         &tempcode,                       /* Where to put code (updated) */
         &ptr,                            /* Input pointer (updated) */
         errorcodeptr,                    /* Where to put an error message */
         (bravalue == OP_ASSERTBACK ||
          bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
         reset_bracount,                  /* True if (?| group */
         skipbytes,                       /* Skip over bracket number */
         cond_depth +
           ((bravalue == OP_COND)?1:0),   /* Depth of condition subpatterns */
         &subfirstchar,                   /* For possible first char */
         &subreqchar,                     /* For possible last char */
         bcptr,                           /* Current branch chain */
         cd,                              /* Tables block */
         (lengthptr == NULL)? NULL :      /* Actual compile phase */
           &length_prevgroup              /* Pre-compile phase */
         ))
      goto FAILED;

    /* If this was an atomic group and there are no capturing groups within it,
    generate OP_ONCE_NC instead of OP_ONCE. */

    if (bravalue == OP_ONCE && cd->bracount <= tempbracount)
      *code = OP_ONCE_NC;

    if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT)
      cd->assert_depth -= 1;

    /* At the end of compiling, code is still pointing to the start of the
    group, while tempcode has been updated to point past the end of the group.
    The pattern pointer (ptr) is on the bracket.

    If this is a conditional bracket, check that there are no more than
    two branches in the group, or just one if it's a DEFINE group. We do this
    in the real compile phase, not in the pre-pass, where the whole group may
    not be available. */

    if (bravalue == OP_COND && lengthptr == NULL)
      {
      pcre_uchar *tc = code;
      int condcount = 0;

      do {
         condcount++;
         tc += GET(tc,1);
         }
      while (*tc != OP_KET);

      /* A DEFINE group is never obeyed inline (the "condition" is always
      false). It must have only one branch. */

      if (code[LINK_SIZE+1] == OP_DEF)
        {
        if (condcount > 1)
          {
          *errorcodeptr = ERR54;
          goto FAILED;
          }
        bravalue = OP_DEF;   /* Just a flag to suppress char handling below */
        }

      /* A "normal" conditional group. If there is just one branch, we must not
      make use of its firstchar or reqchar, because this is equivalent to an
      empty second branch. */

      else
        {
        if (condcount > 2)
          {
          *errorcodeptr = ERR27;
          goto FAILED;
          }
        if (condcount == 1) subfirstchar = subreqchar = REQ_NONE;
        }
      }

    /* Error if hit end of pattern */

    if (*ptr != CHAR_RIGHT_PARENTHESIS)
      {
      *errorcodeptr = ERR14;
      goto FAILED;
      }

    /* In the pre-compile phase, update the length by the length of the group,
    less the brackets at either end. Then reduce the compiled code to just a
    set of non-capturing brackets so that it doesn't use much memory if it is
    duplicated by a quantifier.*/

    if (lengthptr != NULL)
      {
      if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)
        {
        *errorcodeptr = ERR20;
        goto FAILED;
        }
      *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;
      code++;   /* This already contains bravalue */
      PUTINC(code, 0, 1 + LINK_SIZE);
      *code++ = OP_KET;
      PUTINC(code, 0, 1 + LINK_SIZE);
      break;    /* No need to waste time with special character handling */
      }

    /* Otherwise update the main code pointer to the end of the group. */

    code = tempcode;

    /* For a DEFINE group, required and first character settings are not
    relevant. */

    if (bravalue == OP_DEF) break;

    /* Handle updating of the required and first characters for other types of
    group. Update for normal brackets of all kinds, and conditions with two
    branches (see code above). If the bracket is followed by a quantifier with
    zero repeat, we have to back off. Hence the definition of zeroreqchar and
    zerofirstchar outside the main loop so that they can be accessed for the
    back off. */

    zeroreqchar = reqchar;
    zerofirstchar = firstchar;
    groupsetfirstchar = FALSE;

    if (bravalue >= OP_ONCE)
      {
      /* If we have not yet set a firstchar in this branch, take it from the
      subpattern, remembering that it was set here so that a repeat of more
      than one can replicate it as reqchar if necessary. If the subpattern has
      no firstchar, set "none" for the whole branch. In both cases, a zero
      repeat forces firstchar to "none". */

      if (firstchar == REQ_UNSET)
        {
        if (subfirstchar >= 0)
          {
          firstchar = subfirstchar;
          groupsetfirstchar = TRUE;
          }
        else firstchar = REQ_NONE;
        zerofirstchar = REQ_NONE;
        }

      /* If firstchar was previously set, convert the subpattern's firstchar
      into reqchar if there wasn't one, using the vary flag that was in
      existence beforehand. */

      else if (subfirstchar >= 0 && subreqchar < 0)
        subreqchar = subfirstchar | tempreqvary;

      /* If the subpattern set a required byte (or set a first byte that isn't
      really the first byte - see above), set it. */

      if (subreqchar >= 0) reqchar = subreqchar;
      }

    /* For a forward assertion, we take the reqchar, if set. This can be
    helpful if the pattern that follows the assertion doesn't set a different
    char. For example, it's useful for /(?=abcde).+/. We can't set firstchar
    for an assertion, however because it leads to incorrect effect for patterns
    such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead
    of a firstchar. This is overcome by a scan at the end if there's no
    firstchar, looking for an asserted first char. */

    else if (bravalue == OP_ASSERT && subreqchar >= 0) reqchar = subreqchar;
    break;     /* End of processing '(' */


    /* ===================================================================*/
    /* Handle metasequences introduced by \. For ones like \d, the ESC_ values
    are arranged to be the negation of the corresponding OP_values in the
    default case when PCRE_UCP is not set. For the back references, the values
    are ESC_REF plus the reference number. Only back references and those types
    that consume a character may be repeated. We can test for values between
    ESC_b and ESC_Z for the latter; this may have to change if any new ones are
    ever created. */

    case CHAR_BACKSLASH:
    tempptr = ptr;
    c = check_escape(&ptr, errorcodeptr, cd->bracount, options, FALSE);
    if (*errorcodeptr != 0) goto FAILED;

    if (c < 0)
      {
      if (-c == ESC_Q)            /* Handle start of quoted string */
        {
        if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
          ptr += 2;               /* avoid empty string */
            else inescq = TRUE;
        continue;
        }

      if (-c == ESC_E) continue;  /* Perl ignores an orphan \E */

      /* For metasequences that actually match a character, we disable the
      setting of a first character if it hasn't already been set. */

      if (firstchar == REQ_UNSET && -c > ESC_b && -c < ESC_Z)
        firstchar = REQ_NONE;

      /* Set values to reset to if this is followed by a zero repeat. */

      zerofirstchar = firstchar;
      zeroreqchar = reqchar;

      /* \g<name> or \g'name' is a subroutine call by name and \g<n> or \g'n'
      is a subroutine call by number (Oniguruma syntax). In fact, the value
      -ESC_g is returned only for these cases. So we don't need to check for <
      or ' if the value is -ESC_g. For the Perl syntax \g{n} the value is
      -ESC_REF+n, and for the Perl syntax \g{name} the result is -ESC_k (as
      that is a synonym for a named back reference). */

      if (-c == ESC_g)
        {
        const pcre_uchar *p;
        save_hwm = cd->hwm;   /* Normally this is set when '(' is read */
        terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
          CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;

        /* These two statements stop the compiler for warning about possibly
        unset variables caused by the jump to HANDLE_NUMERICAL_RECURSION. In
        fact, because we actually check for a number below, the paths that
        would actually be in error are never taken. */

        skipbytes = 0;
        reset_bracount = FALSE;

        /* Test for a name */

        if (ptr[1] != CHAR_PLUS && ptr[1] != CHAR_MINUS)
          {
          BOOL is_a_number = TRUE;
          for (p = ptr + 1; *p != 0 && *p != terminator; p++)
            {
            if (!MAX_255(*p)) { is_a_number = FALSE; break; }
            if ((cd->ctypes[*p] & ctype_digit) == 0) is_a_number = FALSE;
            if ((cd->ctypes[*p] & ctype_word) == 0) break;
            }
          if (*p != terminator)
            {
            *errorcodeptr = ERR57;
            break;
            }
          if (is_a_number)
            {
            ptr++;
            goto HANDLE_NUMERICAL_RECURSION;
            }
          is_recurse = TRUE;
          goto NAMED_REF_OR_RECURSE;
          }

        /* Test a signed number in angle brackets or quotes. */

        p = ptr + 2;
        while (IS_DIGIT(*p)) p++;
        if (*p != terminator)
          {
          *errorcodeptr = ERR57;
          break;
          }
        ptr++;
        goto HANDLE_NUMERICAL_RECURSION;
        }

      /* \k<name> or \k'name' is a back reference by name (Perl syntax).
      We also support \k{name} (.NET syntax).  */

      if (-c == ESC_k)
        {
        if ((ptr[1] != CHAR_LESS_THAN_SIGN &&
          ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET))
          {
          *errorcodeptr = ERR69;
          break;
          }
        is_recurse = FALSE;
        terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
          CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)?
          CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET;
        goto NAMED_REF_OR_RECURSE;
        }

      /* Back references are handled specially; must disable firstchar if
      not set to cope with cases like (?=(\w+))\1: which would otherwise set
      ':' later. */

      if (-c >= ESC_REF)
        {
        open_capitem *oc;
        recno = -c - ESC_REF;

        HANDLE_REFERENCE:    /* Come here from named backref handling */
        if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
        previous = code;
        *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
        PUT2INC(code, 0, recno);
        cd->backref_map |= (recno < 32)? (1 << recno) : 1;
        if (recno > cd->top_backref) cd->top_backref = recno;

        /* Check to see if this back reference is recursive, that it, it
        is inside the group that it references. A flag is set so that the
        group can be made atomic. */

        for (oc = cd->open_caps; oc != NULL; oc = oc->next)
          {
          if (oc->number == recno)
            {
            oc->flag = TRUE;
            break;
            }
          }
        }

      /* So are Unicode property matches, if supported. */

#ifdef SUPPORT_UCP
      else if (-c == ESC_P || -c == ESC_p)
        {
        BOOL negated;
        int pdata;
        int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
        if (ptype < 0) goto FAILED;
        previous = code;
        *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
        *code++ = ptype;
        *code++ = pdata;
        }
#else

      /* If Unicode properties are not supported, \X, \P, and \p are not
      allowed. */

      else if (-c == ESC_X || -c == ESC_P || -c == ESC_p)
        {
        *errorcodeptr = ERR45;
        goto FAILED;
        }
#endif

      /* For the rest (including \X when Unicode properties are supported), we
      can obtain the OP value by negating the escape value in the default
      situation when PCRE_UCP is not set. When it *is* set, we substitute
      Unicode property tests. Note that \b and \B do a one-character
      lookbehind. */

      else
        {
        if ((-c == ESC_b || -c == ESC_B) && cd->max_lookbehind == 0)
          cd->max_lookbehind = 1;
#ifdef SUPPORT_UCP
        if (-c >= ESC_DU && -c <= ESC_wu)
          {
          nestptr = ptr + 1;                   /* Where to resume */
          ptr = substitutes[-c - ESC_DU] - 1;  /* Just before substitute */
          }
        else
#endif
        /* In non-UTF-8 mode, we turn \C into OP_ALLANY instead of OP_ANYBYTE
        so that it works in DFA mode and in lookbehinds. */

          {
          previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
          *code++ = (!utf && c == -ESC_C)? OP_ALLANY : -c;
          }
        }
      continue;
      }

    /* We have a data character whose value is in c. In UTF-8 mode it may have
    a value > 127. We set its representation in the length/buffer, and then
    handle it as a data character. */

#ifdef SUPPORT_UTF
    if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
      mclength = PRIV(ord2utf)(c, mcbuffer);
    else
#endif

     {
     mcbuffer[0] = c;
     mclength = 1;
     }
    goto ONE_CHAR;


    /* ===================================================================*/
    /* Handle a literal character. It is guaranteed not to be whitespace or #
    when the extended flag is set. If we are in UTF-8 mode, it may be a
    multi-byte literal character. */

    default:
    NORMAL_CHAR:
    mclength = 1;
    mcbuffer[0] = c;

#ifdef SUPPORT_UTF
    if (utf && HAS_EXTRALEN(c))
      ACROSSCHAR(TRUE, ptr[1], mcbuffer[mclength++] = *(++ptr));
#endif

    /* At this point we have the character's bytes in mcbuffer, and the length
    in mclength. When not in UTF-8 mode, the length is always 1. */

    ONE_CHAR:
    previous = code;
    *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR;
    for (c = 0; c < mclength; c++) *code++ = mcbuffer[c];

    /* Remember if \r or \n were seen */

    if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL)
      cd->external_flags |= PCRE_HASCRORLF;

    /* Set the first and required bytes appropriately. If no previous first
    byte, set it from this character, but revert to none on a zero repeat.
    Otherwise, leave the firstchar value alone, and don't change it on a zero
    repeat. */

    if (firstchar == REQ_UNSET)
      {
      zerofirstchar = REQ_NONE;
      zeroreqchar = reqchar;

      /* If the character is more than one byte long, we can set firstchar
      only if it is not to be matched caselessly. */

      if (mclength == 1 || req_caseopt == 0)
        {
        firstchar = mcbuffer[0] | req_caseopt;
        if (mclength != 1) reqchar = code[-1] | cd->req_varyopt;
        }
      else firstchar = reqchar = REQ_NONE;
      }

    /* firstchar was previously set; we can set reqchar only if the length is
    1 or the matching is caseful. */

    else
      {
      zerofirstchar = firstchar;
      zeroreqchar = reqchar;
      if (mclength == 1 || req_caseopt == 0)
        reqchar = code[-1] | req_caseopt | cd->req_varyopt;
      }

    break;            /* End of literal character handling */
    }
  }                   /* end of big loop */


/* Control never reaches here by falling through, only by a goto for all the
error states. Pass back the position in the pattern so that it can be displayed
to the user for diagnosing the error. */

FAILED:
*ptrptr = ptr;
return FALSE;
}




/*************************************************
*     Compile sequence of alternatives           *
*************************************************/

/* On entry, ptr is pointing past the bracket character, but on return it
points to the closing bracket, or vertical bar, or end of string. The code
variable is pointing at the byte into which the BRA operator has been stored.
This function is used during the pre-compile phase when we are trying to find
out the amount of memory needed, as well as during the real compile phase. The
value of lengthptr distinguishes the two phases.

Arguments:
  options        option bits, including any changes for this subpattern
  codeptr        -> the address of the current code pointer
  ptrptr         -> the address of the current pattern pointer
  errorcodeptr   -> pointer to error code variable
  lookbehind     TRUE if this is a lookbehind assertion
  reset_bracount TRUE to reset the count for each branch
  skipbytes      skip this many bytes at start (for brackets and OP_COND)
  cond_depth     depth of nesting for conditional subpatterns
  firstcharptr   place to put the first required character, or a negative number
  reqcharptr     place to put the last required character, or a negative number
  bcptr          pointer to the chain of currently open branches
  cd             points to the data block with tables pointers etc.
  lengthptr      NULL during the real compile phase
                 points to length accumulator during pre-compile phase

Returns:         TRUE on success
*/

static BOOL
compile_regex(int options, pcre_uchar **codeptr, const pcre_uchar **ptrptr,
  int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes,
  int cond_depth, pcre_int32 *firstcharptr, pcre_int32 *reqcharptr,
  branch_chain *bcptr, compile_data *cd, int *lengthptr)
{
const pcre_uchar *ptr = *ptrptr;
pcre_uchar *code = *codeptr;
pcre_uchar *last_branch = code;
pcre_uchar *start_bracket = code;
pcre_uchar *reverse_count = NULL;
open_capitem capitem;
int capnumber = 0;
pcre_int32 firstchar, reqchar;
pcre_int32 branchfirstchar, branchreqchar;
int length;
int orig_bracount;
int max_bracount;
branch_chain bc;

bc.outer = bcptr;
bc.current_branch = code;

firstchar = reqchar = REQ_UNSET;

/* Accumulate the length for use in the pre-compile phase. Start with the
length of the BRA and KET and any extra bytes that are required at the
beginning. We accumulate in a local variable to save frequent testing of
lenthptr for NULL. We cannot do this by looking at the value of code at the
start and end of each alternative, because compiled items are discarded during
the pre-compile phase so that the work space is not exceeded. */

length = 2 + 2*LINK_SIZE + skipbytes;

/* WARNING: If the above line is changed for any reason, you must also change
the code that abstracts option settings at the start of the pattern and makes
them global. It tests the value of length for (2 + 2*LINK_SIZE) in the
pre-compile phase to find out whether anything has yet been compiled or not. */

/* If this is a capturing subpattern, add to the chain of open capturing items
so that we can detect them if (*ACCEPT) is encountered. This is also used to
detect groups that contain recursive back references to themselves. Note that
only OP_CBRA need be tested here; changing this opcode to one of its variants,
e.g. OP_SCBRAPOS, happens later, after the group has been compiled. */

if (*code == OP_CBRA)
  {
  capnumber = GET2(code, 1 + LINK_SIZE);
  capitem.number = capnumber;
  capitem.next = cd->open_caps;
  capitem.flag = FALSE;
  cd->open_caps = &capitem;
  }

/* Offset is set zero to mark that this bracket is still open */

PUT(code, 1, 0);
code += 1 + LINK_SIZE + skipbytes;

/* Loop for each alternative branch */

orig_bracount = max_bracount = cd->bracount;
for (;;)
  {
  /* For a (?| group, reset the capturing bracket count so that each branch
  uses the same numbers. */

  if (reset_bracount) cd->bracount = orig_bracount;

  /* Set up dummy OP_REVERSE if lookbehind assertion */

  if (lookbehind)
    {
    *code++ = OP_REVERSE;
    reverse_count = code;
    PUTINC(code, 0, 0);
    length += 1 + LINK_SIZE;
    }

  /* Now compile the branch; in the pre-compile phase its length gets added
  into the length. */

  if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstchar,
        &branchreqchar, &bc, cond_depth, cd,
        (lengthptr == NULL)? NULL : &length))
    {
    *ptrptr = ptr;
    return FALSE;
    }

  /* Keep the highest bracket count in case (?| was used and some branch
  has fewer than the rest. */

  if (cd->bracount > max_bracount) max_bracount = cd->bracount;

  /* In the real compile phase, there is some post-processing to be done. */

  if (lengthptr == NULL)
    {
    /* If this is the first branch, the firstchar and reqchar values for the
    branch become the values for the regex. */

    if (*last_branch != OP_ALT)
      {
      firstchar = branchfirstchar;
      reqchar = branchreqchar;
      }

    /* If this is not the first branch, the first char and reqchar have to
    match the values from all the previous branches, except that if the
    previous value for reqchar didn't have REQ_VARY set, it can still match,
    and we set REQ_VARY for the regex. */

    else
      {
      /* If we previously had a firstchar, but it doesn't match the new branch,
      we have to abandon the firstchar for the regex, but if there was
      previously no reqchar, it takes on the value of the old firstchar. */

      if (firstchar >= 0 && firstchar != branchfirstchar)
        {
        if (reqchar < 0) reqchar = firstchar;
        firstchar = REQ_NONE;
        }

      /* If we (now or from before) have no firstchar, a firstchar from the
      branch becomes a reqchar if there isn't a branch reqchar. */

      if (firstchar < 0 && branchfirstchar >= 0 && branchreqchar < 0)
          branchreqchar = branchfirstchar;

      /* Now ensure that the reqchars match */

      if ((reqchar & ~REQ_VARY) != (branchreqchar & ~REQ_VARY))
        reqchar = REQ_NONE;
      else reqchar |= branchreqchar;   /* To "or" REQ_VARY */
      }

    /* If lookbehind, check that this branch matches a fixed-length string, and
    put the length into the OP_REVERSE item. Temporarily mark the end of the
    branch with OP_END. If the branch contains OP_RECURSE, the result is -3
    because there may be forward references that we can't check here. Set a
    flag to cause another lookbehind check at the end. Why not do it all at the
    end? Because common, erroneous checks are picked up here and the offset of
    the problem can be shown. */

    if (lookbehind)
      {
      int fixed_length;
      *code = OP_END;
      fixed_length = find_fixedlength(last_branch,  (options & PCRE_UTF8) != 0,
        FALSE, cd);
      DPRINTF(("fixed length = %d\n", fixed_length));
      if (fixed_length == -3)
        {
        cd->check_lookbehind = TRUE;
        }
      else if (fixed_length < 0)
        {
        *errorcodeptr = (fixed_length == -2)? ERR36 :
                        (fixed_length == -4)? ERR70: ERR25;
        *ptrptr = ptr;
        return FALSE;
        }
      else
        {
        if (fixed_length > cd->max_lookbehind)
          cd->max_lookbehind = fixed_length;
        PUT(reverse_count, 0, fixed_length);
        }
      }
    }

  /* Reached end of expression, either ')' or end of pattern. In the real
  compile phase, go back through the alternative branches and reverse the chain
  of offsets, with the field in the BRA item now becoming an offset to the
  first alternative. If there are no alternatives, it points to the end of the
  group. The length in the terminating ket is always the length of the whole
  bracketed item. Return leaving the pointer at the terminating char. */

  if (*ptr != CHAR_VERTICAL_LINE)
    {
    if (lengthptr == NULL)
      {
      int branch_length = (int)(code - last_branch);
      do
        {
        int prev_length = GET(last_branch, 1);
        PUT(last_branch, 1, branch_length);
        branch_length = prev_length;
        last_branch -= branch_length;
        }
      while (branch_length > 0);
      }

    /* Fill in the ket */

    *code = OP_KET;
    PUT(code, 1, (int)(code - start_bracket));
    code += 1 + LINK_SIZE;

    /* If it was a capturing subpattern, check to see if it contained any
    recursive back references. If so, we must wrap it in atomic brackets.
    In any event, remove the block from the chain. */

    if (capnumber > 0)
      {
      if (cd->open_caps->flag)
        {
        memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
          IN_UCHARS(code - start_bracket));
        *start_bracket = OP_ONCE;
        code += 1 + LINK_SIZE;
        PUT(start_bracket, 1, (int)(code - start_bracket));
        *code = OP_KET;
        PUT(code, 1, (int)(code - start_bracket));
        code += 1 + LINK_SIZE;
        length += 2 + 2*LINK_SIZE;
        }
      cd->open_caps = cd->open_caps->next;
      }

    /* Retain the highest bracket number, in case resetting was used. */

    cd->bracount = max_bracount;

    /* Set values to pass back */

    *codeptr = code;
    *ptrptr = ptr;
    *firstcharptr = firstchar;
    *reqcharptr = reqchar;
    if (lengthptr != NULL)
      {
      if (OFLOW_MAX - *lengthptr < length)
        {
        *errorcodeptr = ERR20;
        return FALSE;
        }
      *lengthptr += length;
      }
    return TRUE;
    }

  /* Another branch follows. In the pre-compile phase, we can move the code
  pointer back to where it was for the start of the first branch. (That is,
  pretend that each branch is the only one.)

  In the real compile phase, insert an ALT node. Its length field points back
  to the previous branch while the bracket remains open. At the end the chain
  is reversed. It's done like this so that the start of the bracket has a
  zero offset until it is closed, making it possible to detect recursion. */

  if (lengthptr != NULL)
    {
    code = *codeptr + 1 + LINK_SIZE + skipbytes;
    length += 1 + LINK_SIZE;
    }
  else
    {
    *code = OP_ALT;
    PUT(code, 1, (int)(code - last_branch));
    bc.current_branch = last_branch = code;
    code += 1 + LINK_SIZE;
    }

  ptr++;
  }
/* Control never reaches here */
}




/*************************************************
*          Check for anchored expression         *
*************************************************/

/* Try to find out if this is an anchored regular expression. Consider each
alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
it's anchored. However, if this is a multiline pattern, then only OP_SOD will
be found, because  generates OP_CIRCM in that mode.

We can also consider a regex to be anchored if OP_SOM starts all its branches.
This is the code for \G, which means "match at start of match position, taking
into account the match offset".

A branch is also implicitly anchored if it starts with .* and DOTALL is set,
because that will try the rest of the pattern at all possible matching points,
so there is no point trying again.... er ....

.... except when the .* appears inside capturing parentheses, and there is a
subsequent back reference to those parentheses. We haven't enough information
to catch that case precisely.

At first, the best we could do was to detect when .* was in capturing brackets
and the highest back reference was greater than or equal to that level.
However, by keeping a bitmap of the first 31 back references, we can catch some
of the more common cases more precisely.

Arguments:
  code           points to start of expression (the bracket)
  bracket_map    a bitmap of which brackets we are inside while testing; this
                  handles up to substring 31; after that we just have to take
                  the less precise approach
  backref_map    the back reference bitmap

Returns:     TRUE or FALSE
*/

static BOOL
is_anchored(register const pcre_uchar *code, unsigned int bracket_map,
  unsigned int backref_map)
{
do {
   const pcre_uchar *scode = first_significant_code(
     code + PRIV(OP_lengths)[*code], FALSE);
   register int op = *scode;

   /* Non-capturing brackets */

   if (op == OP_BRA  || op == OP_BRAPOS ||
       op == OP_SBRA || op == OP_SBRAPOS)
     {
     if (!is_anchored(scode, bracket_map, backref_map)) return FALSE;
     }

   /* Capturing brackets */

   else if (op == OP_CBRA  || op == OP_CBRAPOS ||
            op == OP_SCBRA || op == OP_SCBRAPOS)
     {
     int n = GET2(scode, 1+LINK_SIZE);
     int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
     if (!is_anchored(scode, new_map, backref_map)) return FALSE;
     }

   /* Other brackets */

   else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC ||
            op == OP_COND)
     {
     if (!is_anchored(scode, bracket_map, backref_map)) return FALSE;
     }

   /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and
   it isn't in brackets that are or may be referenced. */

   else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||
             op == OP_TYPEPOSSTAR))
     {
     if (scode[1] != OP_ALLANY || (bracket_map & backref_map) != 0)
       return FALSE;
     }

   /* Check for explicit anchoring */

   else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE;
   code += GET(code, 1);
   }
while (*code == OP_ALT);   /* Loop for each alternative */
return TRUE;
}



/*************************************************
*         Check for starting with  or .*        *
*************************************************/

/* This is called to find out if every branch starts with  or .* so that
"first char" processing can be done to speed things up in multiline
matching and for non-DOTALL patterns that start with .* (which must start at
the beginning or after \n). As in the case of is_anchored() (see above), we
have to take account of back references to capturing brackets that contain .*
because in that case we can't make the assumption.

Arguments:
  code           points to start of expression (the bracket)
  bracket_map    a bitmap of which brackets we are inside while testing; this
                  handles up to substring 31; after that we just have to take
                  the less precise approach
  backref_map    the back reference bitmap

Returns:         TRUE or FALSE
*/

static BOOL
is_startline(const pcre_uchar *code, unsigned int bracket_map,
  unsigned int backref_map)
{
do {
   const pcre_uchar *scode = first_significant_code(
     code + PRIV(OP_lengths)[*code], FALSE);
   register int op = *scode;

   /* If we are at the start of a conditional assertion group, *both* the
   conditional assertion *and* what follows the condition must satisfy the test
   for start of line. Other kinds of condition fail. Note that there may be an
   auto-callout at the start of a condition. */

   if (op == OP_COND)
     {
     scode += 1 + LINK_SIZE;
     if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT];
     switch (*scode)
       {
       case OP_CREF:
       case OP_NCREF:
       case OP_RREF:
       case OP_NRREF:
       case OP_DEF:
       return FALSE;

       default:     /* Assertion */
       if (!is_startline(scode, bracket_map, backref_map)) return FALSE;
       do scode += GET(scode, 1); while (*scode == OP_ALT);
       scode += 1 + LINK_SIZE;
       break;
       }
     scode = first_significant_code(scode, FALSE);
     op = *scode;
     }

   /* Non-capturing brackets */

   if (op == OP_BRA  || op == OP_BRAPOS ||
       op == OP_SBRA || op == OP_SBRAPOS)
     {
     if (!is_startline(scode, bracket_map, backref_map)) return FALSE;
     }

   /* Capturing brackets */

   else if (op == OP_CBRA  || op == OP_CBRAPOS ||
            op == OP_SCBRA || op == OP_SCBRAPOS)
     {
     int n = GET2(scode, 1+LINK_SIZE);
     int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
     if (!is_startline(scode, new_map, backref_map)) return FALSE;
     }

   /* Other brackets */

   else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC)
     {
     if (!is_startline(scode, bracket_map, backref_map)) return FALSE;
     }

   /* .* means "start at start or after \n" if it isn't in brackets that
   may be referenced. */

   else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
     {
     if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE;
     }

   /* Check for explicit circumflex */

   else if (op != OP_CIRC && op != OP_CIRCM) return FALSE;

   /* Move on to the next alternative */

   code += GET(code, 1);
   }
while (*code == OP_ALT);  /* Loop for each alternative */
return TRUE;
}



/*************************************************
*       Check for asserted fixed first char      *
*************************************************/

/* During compilation, the "first char" settings from forward assertions are
discarded, because they can cause conflicts with actual literals that follow.
However, if we end up without a first char setting for an unanchored pattern,
it is worth scanning the regex to see if there is an initial asserted first
char. If all branches start with the same asserted char, or with a bracket all
of whose alternatives start with the same asserted char (recurse ad lib), then
we return that char, otherwise -1.

Arguments:
  code       points to start of expression (the bracket)
  inassert   TRUE if in an assertion

Returns:     -1 or the fixed first char
*/

static int
find_firstassertedchar(const pcre_uchar *code, BOOL inassert)
{
register int c = -1;
do {
   int d;
   int xl = (*code == OP_CBRA || *code == OP_SCBRA ||
             *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0;
   const pcre_uchar *scode = first_significant_code(code + 1+LINK_SIZE + xl,
     TRUE);
   register int op = *scode;

   switch(op)
     {
     default:
     return -1;

     case OP_BRA:
     case OP_BRAPOS:
     case OP_CBRA:
     case OP_SCBRA:
     case OP_CBRAPOS:
     case OP_SCBRAPOS:
     case OP_ASSERT:
     case OP_ONCE:
     case OP_ONCE_NC:
     case OP_COND:
     if ((d = find_firstassertedchar(scode, op == OP_ASSERT)) < 0)
       return -1;
     if (c < 0) c = d; else if (c != d) return -1;
     break;

     case OP_EXACT:
     scode += IMM2_SIZE;
     /* Fall through */

     case OP_CHAR:
     case OP_PLUS:
     case OP_MINPLUS:
     case OP_POSPLUS:
     if (!inassert) return -1;
     if (c < 0) c = scode[1];
       else if (c != scode[1]) return -1;
     break;

     case OP_EXACTI:
     scode += IMM2_SIZE;
     /* Fall through */

     case OP_CHARI:
     case OP_PLUSI:
     case OP_MINPLUSI:
     case OP_POSPLUSI:
     if (!inassert) return -1;
     if (c < 0) c = scode[1] | REQ_CASELESS;
       else if (c != scode[1]) return -1;
     break;
     }

   code += GET(code, 1);
   }
while (*code == OP_ALT);
return c;
}



/*************************************************
*        Compile a Regular Expression            *
*************************************************/

/* This function takes a string and returns a pointer to a block of store
holding a compiled version of the expression. The original API for this
function had no error code return variable; it is retained for backwards
compatibility. The new function is given a new name.

Arguments:
  pattern       the regular expression
  options       various option bits
  errorcodeptr  pointer to error code variable (pcre_compile2() only)
                  can be NULL if you don't want a code value
  errorptr      pointer to pointer to error text
  erroroffset   ptr offset in pattern where error was detected
  tables        pointer to character tables or NULL

Returns:        pointer to compiled data block, or NULL on error,
                with errorptr and erroroffset set
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION
COMPILE8(const char *pattern, int options, const char **errorptr,
  int *erroroffset, const unsigned char *tables)
#else
PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION
pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr,
  int *erroroffset, const unsigned char *tables)
#endif
{
#ifdef COMPILE_PCRE8
return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
#else
return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
#endif
}


#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION
pcre_compile2(const char *pattern, int options, int *errorcodeptr,
  const char **errorptr, int *erroroffset, const unsigned char *tables)
#else
PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION
pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr,
  const char **errorptr, int *erroroffset, const unsigned char *tables)
#endif
{
REAL_PCRE *re;
int length = 1;  /* For final END opcode */
pcre_int32 firstchar, reqchar;
int newline;
int errorcode = 0;
int skipatstart = 0;
BOOL utf;
size_t size;
pcre_uchar *code;
const pcre_uchar *codestart;
const pcre_uchar *ptr;
compile_data compile_block;
compile_data *cd = &compile_block;

/* This space is used for "compiling" into during the first phase, when we are
computing the amount of memory that is needed. Compiled items are thrown away
as soon as possible, so that a fairly large buffer should be sufficient for
this purpose. The same space is used in the second phase for remembering where
to fill in forward references to subpatterns. That may overflow, in which case
new memory is obtained from malloc(). */

pcre_uchar cworkspace[COMPILE_WORK_SIZE];

/* Set this early so that early errors get offset 0. */

ptr = (const pcre_uchar *)pattern;

/* We can't pass back an error message if errorptr is NULL; I guess the best we
can do is just return NULL, but we can set a code value if there is a code
pointer. */

if (errorptr == NULL)
  {
  if (errorcodeptr != NULL) *errorcodeptr = 99;
  return NULL;
  }

*errorptr = NULL;
if (errorcodeptr != NULL) *errorcodeptr = ERR0;

/* However, we can give a message for this error */

if (erroroffset == NULL)
  {
  errorcode = ERR16;
  goto PCRE_EARLY_ERROR_RETURN2;
  }

*erroroffset = 0;

/* Set up pointers to the individual character tables */

if (tables == NULL) tables = PRIV(default_tables);
cd->lcc = tables + lcc_offset;
cd->fcc = tables + fcc_offset;
cd->cbits = tables + cbits_offset;
cd->ctypes = tables + ctypes_offset;

/* Check that all undefined public option bits are zero */

if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0)
  {
  errorcode = ERR17;
  goto PCRE_EARLY_ERROR_RETURN;
  }

/* Check for global one-time settings at the start of the pattern, and remember
the offset for later. */

while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&
       ptr[skipatstart+1] == CHAR_ASTERISK)
  {
  int newnl = 0;
  int newbsr = 0;

#ifdef COMPILE_PCRE8
  if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 5) == 0)
    { skipatstart += 7; options |= PCRE_UTF8; continue; }
#endif
#ifdef COMPILE_PCRE16
  if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 6) == 0)
    { skipatstart += 8; options |= PCRE_UTF16; continue; }
#endif
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UCP_RIGHTPAR, 4) == 0)
    { skipatstart += 6; options |= PCRE_UCP; continue; }
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_START_OPT_RIGHTPAR, 13) == 0)
    { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; continue; }

  if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CR_RIGHTPAR, 3) == 0)
    { skipatstart += 5; newnl = PCRE_NEWLINE_CR; }
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LF_RIGHTPAR, 3)  == 0)
    { skipatstart += 5; newnl = PCRE_NEWLINE_LF; }
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CRLF_RIGHTPAR, 5)  == 0)
    { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; }
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANY_RIGHTPAR, 4) == 0)
    { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; }
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANYCRLF_RIGHTPAR, 8) == 0)
    { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; }

  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_ANYCRLF_RIGHTPAR, 12) == 0)
    { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; }
  else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_UNICODE_RIGHTPAR, 12) == 0)
    { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; }

  if (newnl != 0)
    options = (options & ~PCRE_NEWLINE_BITS) | newnl;
  else if (newbsr != 0)
    options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr;
  else break;
  }

/* PCRE_UTF16 has the same value as PCRE_UTF8. */
utf = (options & PCRE_UTF8) != 0;

/* Can't support UTF unless PCRE has been compiled to include the code. The
return of an error code from PRIV(valid_utf)() is a new feature, introduced in
release 8.13. It is passed back from pcre_[dfa_]exec(), but at the moment is
not used here. */

#ifdef SUPPORT_UTF
if (utf && (options & PCRE_NO_UTF8_CHECK) == 0 &&
     (errorcode = PRIV(valid_utf)((PCRE_PUCHAR)pattern, -1, erroroffset)) != 0)
  {
#ifdef COMPILE_PCRE8
  errorcode = ERR44;
#else
  errorcode = ERR74;
#endif
  goto PCRE_EARLY_ERROR_RETURN2;
  }
#else
if (utf)
  {
  errorcode = ERR32;
  goto PCRE_EARLY_ERROR_RETURN;
  }
#endif

/* Can't support UCP unless PCRE has been compiled to include the code. */

#ifndef SUPPORT_UCP
if ((options & PCRE_UCP) != 0)
  {
  errorcode = ERR67;
  goto PCRE_EARLY_ERROR_RETURN;
  }
#endif

/* Check validity of \R options. */

if ((options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) ==
     (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
  {
  errorcode = ERR56;
  goto PCRE_EARLY_ERROR_RETURN;
  }

/* Handle different types of newline. The three bits give seven cases. The
current code allows for fixed one- or two-byte sequences, plus "any" and
"anycrlf". */

switch (options & PCRE_NEWLINE_BITS)
  {
  case 0: newline = NEWLINE; break;   /* Build-time default */
  case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
  case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
  case PCRE_NEWLINE_CR+
       PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
  case PCRE_NEWLINE_ANY: newline = -1; break;
  case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
  default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN;
  }

if (newline == -2)
  {
  cd->nltype = NLTYPE_ANYCRLF;
  }
else if (newline < 0)
  {
  cd->nltype = NLTYPE_ANY;
  }
else
  {
  cd->nltype = NLTYPE_FIXED;
  if (newline > 255)
    {
    cd->nllen = 2;
    cd->nl[0] = (newline >> 8) & 255;
    cd->nl[1] = newline & 255;
    }
  else
    {
    cd->nllen = 1;
    cd->nl[0] = newline;
    }
  }

/* Maximum back reference and backref bitmap. The bitmap records up to 31 back
references to help in deciding whether (.*) can be treated as anchored or not.
*/

cd->top_backref = 0;
cd->backref_map = 0;

/* Reflect pattern for debugging output */

DPRINTF(("------------------------------------------------------------------\n"));
#ifdef PCRE_DEBUG
print_puchar(stdout, (PCRE_PUCHAR)pattern);
#endif
DPRINTF(("\n"));

/* Pretend to compile the pattern while actually just accumulating the length
of memory required. This behaviour is triggered by passing a non-NULL final
argument to compile_regex(). We pass a block of workspace (cworkspace) for it
to compile parts of the pattern into; the compiled code is discarded when it is
no longer needed, so hopefully this workspace will never overflow, though there
is a test for its doing so. */

cd->bracount = cd->final_bracount = 0;
cd->names_found = 0;
cd->name_entry_size = 0;
cd->name_table = NULL;
cd->start_code = cworkspace;
cd->hwm = cworkspace;
cd->start_workspace = cworkspace;
cd->workspace_size = COMPILE_WORK_SIZE;
cd->start_pattern = (const pcre_uchar *)pattern;
cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern));
cd->req_varyopt = 0;
cd->assert_depth = 0;
cd->max_lookbehind = 0;
cd->external_options = options;
cd->external_flags = 0;
cd->open_caps = NULL;

/* Now do the pre-compile. On error, errorcode will be set non-zero, so we
don't need to look at the result of the function here. The initial options have
been put into the cd block so that they can be changed if an option setting is
found within the regex right at the beginning. Bringing initial option settings
outside can help speed up starting point checks. */

ptr += skipatstart;
code = cworkspace;
*code = OP_BRA;
(void)compile_regex(cd->external_options, &code, &ptr, &errorcode, FALSE,
  FALSE, 0, 0, &firstchar, &reqchar, NULL, cd, &length);
if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;

DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
  (int)(cd->hwm - cworkspace)));

if (length > MAX_PATTERN_SIZE)
  {
  errorcode = ERR20;
  goto PCRE_EARLY_ERROR_RETURN;
  }

/* Compute the size of data block needed and get it, either from malloc or
externally provided function. Integer overflow should no longer be possible
because nowadays we limit the maximum value of cd->names_found and
cd->name_entry_size. */

size = sizeof(REAL_PCRE) + (length + cd->names_found * cd->name_entry_size) * sizeof(pcre_uchar);
re = (REAL_PCRE *)(PUBL(malloc))(size);

if (re == NULL)
  {
  errorcode = ERR21;
  goto PCRE_EARLY_ERROR_RETURN;
  }

/* Put in the magic number, and save the sizes, initial options, internal
flags, and character table pointer. NULL is used for the default character
tables. The nullpad field is at the end; it's there to help in the case when a
regex compiled on a system with 4-byte pointers is run on another with 8-byte
pointers. */

re->magic_number = MAGIC_NUMBER;
re->size = (int)size;
re->options = cd->external_options;
re->flags = cd->external_flags;
re->first_char = 0;
re->req_char = 0;
re->name_table_offset = sizeof(REAL_PCRE) / sizeof(pcre_uchar);
re->name_entry_size = cd->name_entry_size;
re->name_count = cd->names_found;
re->ref_count = 0;
re->tables = (tables == PRIV(default_tables))? NULL : tables;
re->nullpad = NULL;

/* The starting points of the name/number translation table and of the code are
passed around in the compile data block. The start/end pattern and initial
options are already set from the pre-compile phase, as is the name_entry_size
field. Reset the bracket count and the names_found field. Also reset the hwm
field; this time it's used for remembering forward references to subpatterns.
*/

cd->final_bracount = cd->bracount;  /* Save for checking forward references */
cd->assert_depth = 0;
cd->bracount = 0;
cd->max_lookbehind = 0;
cd->names_found = 0;
cd->name_table = (pcre_uchar *)re + re->name_table_offset;
codestart = cd->name_table + re->name_entry_size * re->name_count;
cd->start_code = codestart;
cd->hwm = (pcre_uchar *)(cd->start_workspace);
cd->req_varyopt = 0;
cd->had_accept = FALSE;
cd->check_lookbehind = FALSE;
cd->open_caps = NULL;

/* Set up a starting, non-extracting bracket, then compile the expression. On
error, errorcode will be set non-zero, so we don't need to look at the result
of the function here. */

ptr = (const pcre_uchar *)pattern + skipatstart;
code = (pcre_uchar *)codestart;
*code = OP_BRA;
(void)compile_regex(re->options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0,
  &firstchar, &reqchar, NULL, cd, NULL);
re->top_bracket = cd->bracount;
re->top_backref = cd->top_backref;
re->max_lookbehind = cd->max_lookbehind;
re->flags = cd->external_flags | PCRE_MODE;

if (cd->had_accept) reqchar = REQ_NONE;   /* Must disable after (*ACCEPT) */

/* If not reached end of pattern on success, there's an excess bracket. */

if (errorcode == 0 && *ptr != 0) errorcode = ERR22;

/* Fill in the terminating state and check for disastrous overflow, but
if debugging, leave the test till after things are printed out. */

*code++ = OP_END;

#ifndef PCRE_DEBUG
if (code - codestart > length) errorcode = ERR23;
#endif

/* Fill in any forward references that are required. There may be repeated
references; optimize for them, as searching a large regex takes time. */

if (cd->hwm > cd->start_workspace)
  {
  int prev_recno = -1;
  const pcre_uchar *groupptr = NULL;
  while (errorcode == 0 && cd->hwm > cd->start_workspace)
    {
    int offset, recno;
    cd->hwm -= LINK_SIZE;
    offset = GET(cd->hwm, 0);
    recno = GET(codestart, offset);
    if (recno != prev_recno)
      {
      groupptr = PRIV(find_bracket)(codestart, utf, recno);
      prev_recno = recno;
      }
    if (groupptr == NULL) errorcode = ERR53;
      else PUT(((pcre_uchar *)codestart), offset, (int)(groupptr - codestart));
    }
  }

/* If the workspace had to be expanded, free the new memory. */

if (cd->workspace_size > COMPILE_WORK_SIZE)
  (PUBL(free))((void *)cd->start_workspace);

/* Give an error if there's back reference to a non-existent capturing
subpattern. */

if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15;

/* If there were any lookbehind assertions that contained OP_RECURSE
(recursions or subroutine calls), a flag is set for them to be checked here,
because they may contain forward references. Actual recursions can't be fixed
length, but subroutine calls can. It is done like this so that those without
OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The
exceptional ones forgo this. We scan the pattern to check that they are fixed
length, and set their lengths. */

if (cd->check_lookbehind)
  {
  pcre_uchar *cc = (pcre_uchar *)codestart;

  /* Loop, searching for OP_REVERSE items, and process those that do not have
  their length set. (Actually, it will also re-process any that have a length
  of zero, but that is a pathological case, and it does no harm.) When we find
  one, we temporarily terminate the branch it is in while we scan it. */

  for (cc = (pcre_uchar *)PRIV(find_bracket)(codestart, utf, -1);
       cc != NULL;
       cc = (pcre_uchar *)PRIV(find_bracket)(cc, utf, -1))
    {
    if (GET(cc, 1) == 0)
      {
      int fixed_length;
      pcre_uchar *be = cc - 1 - LINK_SIZE + GET(cc, -LINK_SIZE);
      int end_op = *be;
      *be = OP_END;
      fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE,
        cd);
      *be = end_op;
      DPRINTF(("fixed length = %d\n", fixed_length));
      if (fixed_length < 0)
        {
        errorcode = (fixed_length == -2)? ERR36 :
                    (fixed_length == -4)? ERR70 : ERR25;
        break;
        }
      if (fixed_length > cd->max_lookbehind) cd->max_lookbehind = fixed_length;
      PUT(cc, 1, fixed_length);
      }
    cc += 1 + LINK_SIZE;
    }
  }

/* Failed to compile, or error while post-processing */

if (errorcode != 0)
  {
  (PUBL(free))(re);
  PCRE_EARLY_ERROR_RETURN:
  *erroroffset = (int)(ptr - (const pcre_uchar *)pattern);
  PCRE_EARLY_ERROR_RETURN2:
  *errorptr = find_error_text(errorcode);
  if (errorcodeptr != NULL) *errorcodeptr = errorcode;
  return NULL;
  }

/* If the anchored option was not passed, set the flag if we can determine that
the pattern is anchored by virtue of  characters or \A or anything else (such
as starting with .* when DOTALL is set).

Otherwise, if we know what the first byte has to be, save it, because that
speeds up unanchored matches no end. If not, see if we can set the
PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
start with . and also when all branches start with .* for non-DOTALL matches.
*/

if ((re->options & PCRE_ANCHORED) == 0)
  {
  if (is_anchored(codestart, 0, cd->backref_map))
    re->options |= PCRE_ANCHORED;
  else
    {
    if (firstchar < 0)
      firstchar = find_firstassertedchar(codestart, FALSE);
    if (firstchar >= 0)   /* Remove caseless flag for non-caseable chars */
      {
#ifdef COMPILE_PCRE8
      re->first_char = firstchar & 0xff;
#else
#ifdef COMPILE_PCRE16
      re->first_char = firstchar & 0xffff;
#endif
#endif
      if ((firstchar & REQ_CASELESS) != 0)
        {
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
        /* We ignore non-ASCII first chars in 8 bit mode. */
        if (utf)
          {
          if (re->first_char < 128)
            {
            if (cd->fcc[re->first_char] != re->first_char)
              re->flags |= PCRE_FCH_CASELESS;
            }
          else if (UCD_OTHERCASE(re->first_char) != re->first_char)
            re->flags |= PCRE_FCH_CASELESS;
          }
        else
#endif
        if (MAX_255(re->first_char)
            && cd->fcc[re->first_char] != re->first_char)
          re->flags |= PCRE_FCH_CASELESS;
        }

      re->flags |= PCRE_FIRSTSET;
      }
    else if (is_startline(codestart, 0, cd->backref_map))
      re->flags |= PCRE_STARTLINE;
    }
  }

/* For an anchored pattern, we use the "required byte" only if it follows a
variable length item in the regex. Remove the caseless flag for non-caseable
bytes. */

if (reqchar >= 0 &&
     ((re->options & PCRE_ANCHORED) == 0 || (reqchar & REQ_VARY) != 0))
  {
#ifdef COMPILE_PCRE8
  re->req_char = reqchar & 0xff;
#else
#ifdef COMPILE_PCRE16
  re->req_char = reqchar & 0xffff;
#endif
#endif
  if ((reqchar & REQ_CASELESS) != 0)
    {
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
    /* We ignore non-ASCII first chars in 8 bit mode. */
    if (utf)
      {
      if (re->req_char < 128)
        {
        if (cd->fcc[re->req_char] != re->req_char)
          re->flags |= PCRE_RCH_CASELESS;
        }
      else if (UCD_OTHERCASE(re->req_char) != re->req_char)
        re->flags |= PCRE_RCH_CASELESS;
      }
    else
#endif
    if (MAX_255(re->req_char) && cd->fcc[re->req_char] != re->req_char)
      re->flags |= PCRE_RCH_CASELESS;
    }

  re->flags |= PCRE_REQCHSET;
  }

/* Print out the compiled data if debugging is enabled. This is never the
case when building a production library. */

#ifdef PCRE_DEBUG
printf("Length = %d top_bracket = %d top_backref = %d\n",
  length, re->top_bracket, re->top_backref);

printf("Options=%08x\n", re->options);

if ((re->flags & PCRE_FIRSTSET) != 0)
  {
  pcre_uchar ch = re->first_char;
  const char *caseless =
    ((re->flags & PCRE_FCH_CASELESS) == 0)? "" : " (caseless)";
  if (PRINTABLE(ch)) printf("First char = %c%s\n", ch, caseless);
    else printf("First char = \\x%02x%s\n", ch, caseless);
  }

if ((re->flags & PCRE_REQCHSET) != 0)
  {
  pcre_uchar ch = re->req_char;
  const char *caseless =
    ((re->flags & PCRE_RCH_CASELESS) == 0)? "" : " (caseless)";
  if (PRINTABLE(ch)) printf("Req char = %c%s\n", ch, caseless);
    else printf("Req char = \\x%02x%s\n", ch, caseless);
  }

#ifdef COMPILE_PCRE8
PRINTIN8((pcre *)re, stdout, TRUE);
#else
pcre16_printint((pcre *)re, stdout, TRUE);
#endif

/* This check is done here in the debugging case so that the code that
was compiled can be seen. */

if (code - codestart > length)
  {
  (PUBL(free))(re);
  *errorptr = find_error_text(ERR23);
  *erroroffset = ptr - (pcre_uchar *)pattern;
  if (errorcodeptr != NULL) *errorcodeptr = ERR23;
  return NULL;
  }
#endif   /* PCRE_DEBUG */

#ifdef COMPILE_PCRE8
return (pcre *)re;
#else
return (pcre16 *)re;
#endif
}

/* End of COMPILE8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_compile.c converted to COMPILE8*/
/*autoconv-0013 COMPILE8 line: 41 pcre_compile replaced by COMPILE8*/
/*autoconv-0010 COMPILE8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 COMPILE8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 COMPILE8 line: 56 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 COMPILE8 line: 60 pcretest replaced by PCRETEST*/
/*autoconv-0013 COMPILE8 line: 65 pcre_printint replaced by PRINTIN8*/
/*autoconv-0011 COMPILE8 line: 67 pcre_printint.c replaced by PRINTIN8.c*/
/*autoconv-0013 COMPILE8 line: 2029 pcre_study replaced by STUDY8*/
/*autoconv-0013 COMPILE8 line: 5387 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 COMPILE8 line: 7610 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 COMPILE8 line: 8187 pcre_printint replaced by PRINTIN8*/
/*autoconv-0013 COMPILE8 line: 8212 pcre_compile replaced by COMPILE8*/
./ ADD NAME=PCREXEC8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

/* This module contains PCREXEC8(), the externally visible function that does
pattern matching using an NFA algorithm, trying to mimic Perl as closely as
possible. There are also some static supporting functions. */

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#define NLBLOCK md             /* Block containing newline information */
#define PSSTART start_subject  /* Field containing processed string start */
#define PSEND   end_subject    /* Field containing processed string end */

#include "INTERNA8.h"

/* Undefine some potentially clashing cpp symbols */

#undef min
#undef max

/* Values for setting in md->match_function_type to indicate two special types
of call to match(). We do it this way to save on using another stack variable,
as stack usage is to be discouraged. */

#define MATCH_CONDASSERT     1  /* Called to check a condition assertion */
#define MATCH_CBEGROUP       2  /* Could-be-empty unlimited repeat group */

/* Non-error returns from the match() function. Error returns are externally
defined PCRE_ERROR_xxx codes, which are all negative. */

#define MATCH_MATCH        1
#define MATCH_NOMATCH      0

/* Special internal returns from the match() function. Make them sufficiently
negative to avoid the external error codes. */

#define MATCH_ACCEPT       (-999)
#define MATCH_COMMIT       (-998)
#define MATCH_KETRPOS      (-997)
#define MATCH_ONCE         (-996)
#define MATCH_PRUNE        (-995)
#define MATCH_SKIP         (-994)
#define MATCH_SKIP_ARG     (-993)
#define MATCH_THEN         (-992)

/* Maximum number of ints of offset to save on the stack for recursive calls.
If the offset vector is bigger, malloc is used. This should be a multiple of 3,
because the offset vector is always a multiple of 3 long. */

#define REC_STACK_SAVE_MAX 30

/* Min and max values for the common repeats; for the maxima, 0 => infinity */

static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };



#ifdef PCRE_DEBUG
/*************************************************
*        Debugging function to print chars       *
*************************************************/

/* Print a sequence of chars in printable format, stopping at the end of the
subject if the requested.

Arguments:
  p           points to characters
  length      number to print
  is_subject  TRUE if printing from within md->start_subject
  md          pointer to matching data block, if is_subject is TRUE

Returns:     nothing
*/

static void
pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)
{
unsigned int c;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
while (length-- > 0)
  if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);
}
#endif



/*************************************************
*          Match a back-reference                *
*************************************************/

/* Normally, if a back reference hasn't been set, the length that is passed is
negative, so the match always fails. However, in JavaScript compatibility mode,
the length passed is zero. Note that in caseless UTF-8 mode, the number of
subject bytes matched may be different to the number of reference bytes.

Arguments:
  offset      index into the offset vector
  eptr        pointer into the subject
  length      length of reference to be matched (number of bytes)
  md          points to match data block
  caseless    TRUE if caseless

Returns:      >= 0 the number of subject bytes matched
              -1 no match
              -2 partial match; always given if at end subject
*/

static int
match_ref(int offset, register PCRE_PUCHAR eptr, int length, match_data *md,
  BOOL caseless)
{
PCRE_PUCHAR eptr_start = eptr;
register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset];

#ifdef PCRE_DEBUG
if (eptr >= md->end_subject)
  printf("matching subject <null>");
else
  {
  printf("matching subject ");
  pchars(eptr, length, TRUE, md);
  }
printf(" against backref ");
pchars(p, length, FALSE, md);
printf("\n");
#endif

/* Always fail if reference not set (and not JavaScript compatible - in that
case the length is passed as zero). */

if (length < 0) return -1;

/* Separate the caseless case for speed. In UTF-8 mode we can only do this
properly if Unicode properties are supported. Otherwise, we can check only
ASCII characters. */

if (caseless)
  {
#ifdef SUPPORT_UTF
#ifdef SUPPORT_UCP
  if (md->utf)
    {
    /* Match characters up to the end of the reference. NOTE: the number of
    bytes matched may differ, because there are some characters whose upper and
    lower case versions code as different numbers of bytes. For example, U+023A
    (2 bytes in UTF-8) is the upper case version of U+2C65 (3 bytes in UTF-8);
    a sequence of 3 of the former uses 6 bytes, as does a sequence of two of
    the latter. It is important, therefore, to check the length along the
    reference, not along the subject (earlier code did this wrong). */

    PCRE_PUCHAR endptr = p + length;
    while (p < endptr)
      {
      int c, d;
      if (eptr >= md->end_subject) return -2;   /* Partial match */
      GETCHARINC(c, eptr);
      GETCHARINC(d, p);
      if (c != d && c != UCD_OTHERCASE(d)) return -1;
      }
    }
  else
#endif
#endif

  /* The same code works when not in UTF-8 mode and in UTF-8 mode when there
  is no UCP support. */
    {
    while (length-- > 0)
      {
      if (eptr >= md->end_subject) return -2;   /* Partial match */
      if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1;
      p++;
      eptr++;
      }
    }
  }

/* In the caseful case, we can just compare the bytes, whether or not we
are in UTF-8 mode. */

else
  {
  while (length-- > 0)
    {
    if (eptr >= md->end_subject) return -2;   /* Partial match */
    if (*p++ != *eptr++) return -1;
    }
  }

return (int)(eptr - eptr_start);
}



/***************************************************************************
****************************************************************************
                   RECURSION IN THE match() FUNCTION

The match() function is highly recursive, though not every recursive call
increases the recursive depth. Nevertheless, some regular expressions can cause
it to recurse to a great depth. I was writing for Unix, so I just let it call
itself recursively. This uses the stack for saving everything that has to be
saved for a recursive call. On Unix, the stack can be large, and this works
fine.

It turns out that on some non-Unix-like systems there are problems with
programs that use a lot of stack. (This despite the fact that every last chip
has oodles of memory these days, and techniques for extending the stack have
been known for decades.) So....

There is a fudge, triggered by defining NO_RECURSE, which avoids recursive
calls by keeping local variables that need to be preserved in blocks of memory
obtained from malloc() instead instead of on the stack. Macros are used to
achieve this so that the actual code doesn't look very different to what it
always used to.

The original heap-recursive code used longjmp(). However, it seems that this
can be very slow on some operating systems. Following a suggestion from Stan
Switzer, the use of longjmp() has been abolished, at the cost of having to
provide a unique number for each call to RMATCH. There is no way of generating
a sequence of numbers at compile time in C. I have given them names, to make
them stand out more clearly.

Crude tests on x86 Linux show a small speedup of around 5-8%. However, on
FreeBSD, avoiding longjmp() more than halves the time taken to run the standard
tests. Furthermore, not using longjmp() means that local dynamic variables
don't have indeterminate values; this has meant that the frame size can be
reduced because the result can be "passed back" by straight setting of the
variable instead of being passed in the frame.
****************************************************************************
***************************************************************************/

/* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN
below must be updated in sync.  */

enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM6,  RM7,  RM8,  RM9,  RM10,
       RM11,  RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
       RM21,  RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
       RM31,  RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,
       RM41,  RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,
       RM51,  RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,
       RM61,  RM62, RM63, RM64, RM65, RM66 };

/* These versions of the macros use the stack, as normal. There are debugging
versions and production versions. Note that the "rw" argument of RMATCH isn't
actually used in this definition. */

#ifndef NO_RECURSE
#define REGISTER register

#ifdef PCRE_DEBUG
#define RMATCH(ra,rb,rc,rd,re,rw) \
  { \
  printf("match() called in line %d\n", __LINE__); \
  rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1); \
  printf("to line %d\n", __LINE__); \
  }
#define RRETURN(ra) \
  { \
  printf("match() returned %d from line %d ", ra, __LINE__); \
  return ra; \
  }
#else
#define RMATCH(ra,rb,rc,rd,re,rw) \
  rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1)
#define RRETURN(ra) return ra
#endif

#else


/* These versions of the macros manage a private stack on the heap. Note that
the "rd" argument of RMATCH isn't actually used in this definition. It's the md
argument of match(), which never changes. */

#define REGISTER

#define RMATCH(ra,rb,rc,rd,re,rw)\
  {\
  heapframe *newframe = frame->Xnextframe;\
  if (newframe == NULL)\
    {\
    newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\
    if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
    newframe->Xnextframe = NULL;\
    frame->Xnextframe = newframe;\
    }\
  frame->Xwhere = rw;\
  newframe->Xeptr = ra;\
  newframe->Xecode = rb;\
  newframe->Xmstart = mstart;\
  newframe->Xoffset_top = rc;\
  newframe->Xeptrb = re;\
  newframe->Xrdepth = frame->Xrdepth + 1;\
  newframe->Xprevframe = frame;\
  frame = newframe;\
  DPRINTF(("restarting from line %d\n", __LINE__));\
  goto HEAP_RECURSE;\
  L_##rw:\
  DPRINTF(("jumped back to line %d\n", __LINE__));\
  }

#define RRETURN(ra)\
  {\
  heapframe *oldframe = frame;\
  frame = oldframe->Xprevframe;\
  if (frame != NULL)\
    {\
    rrc = ra;\
    goto HEAP_RETURN;\
    }\
  return ra;\
  }


/* Structure for remembering the local variables in a private frame */

typedef struct heapframe {
  struct heapframe *Xprevframe;
  struct heapframe *Xnextframe;

  /* Function arguments that may change */

  PCRE_PUCHAR Xeptr;
  const pcre_uchar *Xecode;
  PCRE_PUCHAR Xmstart;
  int Xoffset_top;
  eptrblock *Xeptrb;
  unsigned int Xrdepth;

  /* Function local variables */

  PCRE_PUCHAR Xcallpat;
#ifdef SUPPORT_UTF
  PCRE_PUCHAR Xcharptr;
#endif
  PCRE_PUCHAR Xdata;
  PCRE_PUCHAR Xnext;
  PCRE_PUCHAR Xpp;
  PCRE_PUCHAR Xprev;
  PCRE_PUCHAR Xsaved_eptr;

  recursion_info Xnew_recursive;

  BOOL Xcur_is_word;
  BOOL Xcondition;
  BOOL Xprev_is_word;

#ifdef SUPPORT_UCP
  int Xprop_type;
  int Xprop_value;
  int Xprop_fail_result;
  int Xoclength;
  pcre_uchar Xocchars[6];
#endif

  int Xcodelink;
  int Xctype;
  unsigned int Xfc;
  int Xfi;
  int Xlength;
  int Xmax;
  int Xmin;
  int Xnumber;
  int Xoffset;
  int Xop;
  int Xsave_capture_last;
  int Xsave_offset1, Xsave_offset2, Xsave_offset3;
  int Xstacksave[REC_STACK_SAVE_MAX];

  eptrblock Xnewptrb;

  /* Where to jump back to */

  int Xwhere;

} heapframe;

#endif


/***************************************************************************
***************************************************************************/



/*************************************************
*         Match from current position            *
*************************************************/

/* This function is called recursively in many circumstances. Whenever it
returns a negative (error) response, the outer incarnation must also return the
same response. */

/* These macros pack up tests that are used for partial matching, and which
appear several times in the code. We set the "hit end" flag if the pointer is
at the end of the subject and also past the start of the subject (i.e.
something has been matched). For hard partial matching, we then return
immediately. The second one is used when we already know we are past the end of
the subject. */

#define CHECK_PARTIAL()\
  if (md->partial != 0 && eptr >= md->end_subject && \
      eptr > md->start_used_ptr) \
    { \
    md->hitend = TRUE; \
    if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
    }

#define SCHECK_PARTIAL()\
  if (md->partial != 0 && eptr > md->start_used_ptr) \
    { \
    md->hitend = TRUE; \
    if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
    }


/* Performance note: It might be tempting to extract commonly used fields from
the md structure (e.g. utf, end_subject) into individual variables to improve
performance. Tests using gcc on a SPARC disproved this; in the first case, it
made performance worse.

Arguments:
   eptr        pointer to current character in subject
   ecode       pointer to current position in compiled code
   mstart      pointer to the current match start position (can be modified
                 by encountering \K)
   offset_top  current top pointer
   md          pointer to "static" info for the match
   eptrb       pointer to chain of blocks containing eptr at start of
                 brackets - for testing for empty matches
   rdepth      the recursion depth

Returns:       MATCH_MATCH if matched            )  these values are >= 0
               MATCH_NOMATCH if failed to match  )
               a negative MATCH_xxx value for PRUNE, SKIP, etc
               a negative PCRE_ERROR_xxx value if aborted by an error condition
                 (e.g. stopped by repeated call or recursion limit)
*/

static int
match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode,
  PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb,
  unsigned int rdepth)
{
/* These variables do not need to be preserved over recursion in this function,
so they can be ordinary variables in all cases. Mark some of them with
"register" because they are used a lot in loops. */

register int  rrc;         /* Returns from recursive calls */
register int  i;           /* Used for loops not involving calls to RMATCH() */
register unsigned int c;   /* Character values not kept over RMATCH() calls */
register BOOL utf;         /* Local copy of UTF flag for speed */

BOOL minimize, possessive; /* Quantifier options */
BOOL caseless;
int condcode;

/* When recursion is not being used, all "local" variables that have to be
preserved over calls to RMATCH() are part of a "frame". We set up the top-level
frame on the stack here; subsequent instantiations are obtained from the heap
whenever RMATCH() does a "recursion". See the macro definitions above. Putting
the top-level on the stack rather than malloc-ing them all gives a performance
boost in many cases where there is not much "recursion". */

#ifdef NO_RECURSE
heapframe *frame = (heapframe *)md->match_frames_base;

/* Copy in the original argument variables */

frame->Xeptr = eptr;
frame->Xecode = ecode;
frame->Xmstart = mstart;
frame->Xoffset_top = offset_top;
frame->Xeptrb = eptrb;
frame->Xrdepth = rdepth;

/* This is where control jumps back to to effect "recursion" */

HEAP_RECURSE:

/* Macros make the argument variables come from the current frame */

#define eptr               frame->Xeptr
#define ecode              frame->Xecode
#define mstart             frame->Xmstart
#define offset_top         frame->Xoffset_top
#define eptrb              frame->Xeptrb
#define rdepth             frame->Xrdepth

/* Ditto for the local variables */

#ifdef SUPPORT_UTF
#define charptr            frame->Xcharptr
#endif
#define callpat            frame->Xcallpat
#define codelink           frame->Xcodelink
#define data               frame->Xdata
#define next               frame->Xnext
#define pp                 frame->Xpp
#define prev               frame->Xprev
#define saved_eptr         frame->Xsaved_eptr

#define new_recursive      frame->Xnew_recursive

#define cur_is_word        frame->Xcur_is_word
#define condition          frame->Xcondition
#define prev_is_word       frame->Xprev_is_word

#ifdef SUPPORT_UCP
#define prop_type          frame->Xprop_type
#define prop_value         frame->Xprop_value
#define prop_fail_result   frame->Xprop_fail_result
#define oclength           frame->Xoclength
#define occhars            frame->Xocchars
#endif

#define ctype              frame->Xctype
#define fc                 frame->Xfc
#define fi                 frame->Xfi
#define length             frame->Xlength
#define max                frame->Xmax
#define min                frame->Xmin
#define number             frame->Xnumber
#define offset             frame->Xoffset
#define op                 frame->Xop
#define save_capture_last  frame->Xsave_capture_last
#define save_offset1       frame->Xsave_offset1
#define save_offset2       frame->Xsave_offset2
#define save_offset3       frame->Xsave_offset3
#define stacksave          frame->Xstacksave

#define newptrb            frame->Xnewptrb

/* When recursion is being used, local variables are allocated on the stack and
get preserved during recursion in the normal way. In this environment, fi and
i, and fc and c, can be the same variables. */

#else         /* NO_RECURSE not defined */
#define fi i
#define fc c

/* Many of the following variables are used only in small blocks of the code.
My normal style of coding would have declared them within each of those blocks.
However, in order to accommodate the version of this code that uses an external
"stack" implemented on the heap, it is easier to declare them all here, so the
declarations can be cut out in a block. The only declarations within blocks
below are for variables that do not have to be preserved over a recursive call
to RMATCH(). */

#ifdef SUPPORT_UTF
const pcre_uchar *charptr;
#endif
const pcre_uchar *callpat;
const pcre_uchar *data;
const pcre_uchar *next;
PCRE_PUCHAR       pp;
const pcre_uchar *prev;
PCRE_PUCHAR       saved_eptr;

recursion_info new_recursive;

BOOL cur_is_word;
BOOL condition;
BOOL prev_is_word;

#ifdef SUPPORT_UCP
int prop_type;
int prop_value;
int prop_fail_result;
int oclength;
pcre_uchar occhars[6];
#endif

int codelink;
int ctype;
int length;
int max;
int min;
int number;
int offset;
int op;
int save_capture_last;
int save_offset1, save_offset2, save_offset3;
int stacksave[REC_STACK_SAVE_MAX];

eptrblock newptrb;

/* There is a special fudge for calling match() in a way that causes it to
measure the size of its basic stack frame when the stack is being used for
recursion. The second argument (ecode) being NULL triggers this behaviour. It
cannot normally ever be NULL. The return is the negated value of the frame
size. */

if (ecode == NULL)
  {
  if (rdepth == 0)
    return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
  else
    {
    int len = (char *)&rdepth - (char *)eptr;
    return (len > 0)? -len : len;
    }
  }
#endif     /* NO_RECURSE */

/* To save space on the stack and in the heap frame, I have doubled up on some
of the local variables that are used only in localised parts of the code, but
still need to be preserved over recursive calls of match(). These macros define
the alternative names that are used. */

#define allow_zero    cur_is_word
#define cbegroup      condition
#define code_offset   codelink
#define condassert    condition
#define matched_once  prev_is_word
#define foc           number
#define save_mark     data

/* These statements are here to stop the compiler complaining about unitialized
variables. */

#ifdef SUPPORT_UCP
prop_value = 0;
prop_fail_result = 0;
#endif


/* This label is used for tail recursion, which is used in a few cases even
when NO_RECURSE is not defined, in order to reduce the amount of stack that is
used. Thanks to Ian Taylor for noticing this possibility and sending the
original patch. */

TAIL_RECURSE:

/* OK, now we can get on with the real code of the function. Recursive calls
are specified by the macro RMATCH and RRETURN is used to return. When
NO_RECURSE is *not* defined, these just turn into a recursive call to match()
and a "return", respectively (possibly with some debugging if PCRE_DEBUG is
defined). However, RMATCH isn't like a function call because it's quite a
complicated macro. It has to be used in one particular way. This shouldn't,
however, impact performance when true recursion is being used. */

#ifdef SUPPORT_UTF
utf = md->utf;       /* Local copy of the flag */
#else
utf = FALSE;
#endif

/* First check that we haven't called match() too many times, or that we
haven't exceeded the recursive call limit. */

if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);
if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT);

/* At the start of a group with an unlimited repeat that may match an empty
string, the variable md->match_function_type is set to MATCH_CBEGROUP. It is
done this way to save having to use another function argument, which would take
up space on the stack. See also MATCH_CONDASSERT below.

When MATCH_CBEGROUP is set, add the current subject pointer to the chain of
such remembered pointers, to be checked when we hit the closing ket, in order
to break infinite loops that match no characters. When match() is called in
other circumstances, don't add to the chain. The MATCH_CBEGROUP feature must
NOT be used with tail recursion, because the memory block that is used is on
the stack, so a new one may be required for each match(). */

if (md->match_function_type == MATCH_CBEGROUP)
  {
  newptrb.epb_saved_eptr = eptr;
  newptrb.epb_prev = eptrb;
  eptrb = &newptrb;
  md->match_function_type = 0;
  }

/* Now start processing the opcodes. */

for (;;)
  {
  minimize = possessive = FALSE;
  op = *ecode;

  switch(op)
    {
    case OP_MARK:
    md->nomatch_mark = ecode + 2;
    md->mark = NULL;    /* In case previously set by assertion */
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
      eptrb, RM55);
    if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
         md->mark == NULL) md->mark = ecode + 2;

    /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an
    argument, and we must check whether that argument matches this MARK's
    argument. It is passed back in md->start_match_ptr (an overloading of that
    variable). If it does match, we reset that variable to the current subject
    position and return MATCH_SKIP. Otherwise, pass back the return code
    unaltered. */

    else if (rrc == MATCH_SKIP_ARG &&
        STRCMP_UC_UC(ecode + 2, md->start_match_ptr) == 0)
      {
      md->start_match_ptr = eptr;
      RRETURN(MATCH_SKIP);
      }
    RRETURN(rrc);

    case OP_FAIL:
    RRETURN(MATCH_NOMATCH);

    /* COMMIT overrides PRUNE, SKIP, and THEN */

    case OP_COMMIT:
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
      eptrb, RM52);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&
        rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG &&
        rrc != MATCH_THEN)
      RRETURN(rrc);
    RRETURN(MATCH_COMMIT);

    /* PRUNE overrides THEN */

    case OP_PRUNE:
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
      eptrb, RM51);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
    RRETURN(MATCH_PRUNE);

    case OP_PRUNE_ARG:
    md->nomatch_mark = ecode + 2;
    md->mark = NULL;    /* In case previously set by assertion */
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
      eptrb, RM56);
    if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
         md->mark == NULL) md->mark = ecode + 2;
    if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
    RRETURN(MATCH_PRUNE);

    /* SKIP overrides PRUNE and THEN */

    case OP_SKIP:
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
      eptrb, RM53);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
      RRETURN(rrc);
    md->start_match_ptr = eptr;   /* Pass back current position */
    RRETURN(MATCH_SKIP);

    /* Note that, for Perl compatibility, SKIP with an argument does NOT set
    nomatch_mark. There is a flag that disables this opcode when re-matching a
    pattern that ended with a SKIP for which there was not a matching MARK. */

    case OP_SKIP_ARG:
    if (md->ignore_skip_arg)
      {
      ecode += PRIV(OP_lengths)[*ecode] + ecode[1];
      break;
      }
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
      eptrb, RM57);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
      RRETURN(rrc);

    /* Pass back the current skip name by overloading md->start_match_ptr and
    returning the special MATCH_SKIP_ARG return code. This will either be
    caught by a matching MARK, or get to the top, where it causes a rematch
    with the md->ignore_skip_arg flag set. */

    md->start_match_ptr = ecode + 2;
    RRETURN(MATCH_SKIP_ARG);

    /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that
    the branch in which it occurs can be determined. Overload the start of
    match pointer to do this. */

    case OP_THEN:
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
      eptrb, RM54);
    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
    md->start_match_ptr = ecode;
    RRETURN(MATCH_THEN);

    case OP_THEN_ARG:
    md->nomatch_mark = ecode + 2;
    md->mark = NULL;    /* In case previously set by assertion */
    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top,
      md, eptrb, RM58);
    if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
         md->mark == NULL) md->mark = ecode + 2;
    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
    md->start_match_ptr = ecode;
    RRETURN(MATCH_THEN);

    /* Handle an atomic group that does not contain any capturing parentheses.
    This can be handled like an assertion. Prior to 8.13, all atomic groups
    were handled this way. In 8.13, the code was changed as below for ONCE, so
    that backups pass through the group and thereby reset captured values.
    However, this uses a lot more stack, so in 8.20, atomic groups that do not
    contain any captures generate OP_ONCE_NC, which can be handled in the old,
    less stack intensive way.

    Check the alternative branches in turn - the matching won't pass the KET
    for this kind of subpattern. If any one branch matches, we carry on as at
    the end of a normal bracket, leaving the subject pointer, but resetting
    the start-of-match value in case it was changed by \K. */

    case OP_ONCE_NC:
    prev = ecode;
    saved_eptr = eptr;
    save_mark = md->mark;
    do
      {
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64);
      if (rrc == MATCH_MATCH)  /* Note: _not_ MATCH_ACCEPT */
        {
        mstart = md->start_match_ptr;
        break;
        }
      if (rrc == MATCH_THEN)
        {
        next = ecode + GET(ecode,1);
        if (md->start_match_ptr < next &&
            (*ecode == OP_ALT || *next == OP_ALT))
          rrc = MATCH_NOMATCH;
        }

      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      ecode += GET(ecode,1);
      md->mark = save_mark;
      }
    while (*ecode == OP_ALT);

    /* If hit the end of the group (which could be repeated), fail */

    if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH);

    /* Continue as from after the group, updating the offsets high water
    mark, since extracts may have been taken. */

    do ecode += GET(ecode, 1); while (*ecode == OP_ALT);

    offset_top = md->end_offset_top;
    eptr = md->end_match_ptr;

    /* For a non-repeating ket, just continue at this level. This also
    happens for a repeating ket if no characters were matched in the group.
    This is the forcible breaking of infinite loops as implemented in Perl
    5.005. */

    if (*ecode == OP_KET || eptr == saved_eptr)
      {
      ecode += 1+LINK_SIZE;
      break;
      }

    /* The repeating kets try the rest of the pattern or restart from the
    preceding bracket, in the appropriate order. The second "call" of match()
    uses tail recursion, to avoid using another stack frame. */

    if (*ecode == OP_KETRMIN)
      {
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65);
      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      ecode = prev;
      goto TAIL_RECURSE;
      }
    else  /* OP_KETRMAX */
      {
      RMATCH(eptr, prev, offset_top, md, eptrb, RM66);
      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      ecode += 1 + LINK_SIZE;
      goto TAIL_RECURSE;
      }
    /* Control never gets here */

    /* Handle a capturing bracket, other than those that are possessive with an
    unlimited repeat. If there is space in the offset vector, save the current
    subject position in the working slot at the top of the vector. We mustn't
    change the current values of the data slot, because they may be set from a
    previous iteration of this group, and be referred to by a reference inside
    the group. A failure to match might occur after the group has succeeded,
    if something later on doesn't match. For this reason, we need to restore
    the working value and also the values of the final offsets, in case they
    were set by a previous iteration of the same bracket.

    If there isn't enough space in the offset vector, treat this as if it were
    a non-capturing bracket. Don't worry about setting the flag for the error
    case here; that is handled in the code for KET. */

    case OP_CBRA:
    case OP_SCBRA:
    number = GET2(ecode, 1+LINK_SIZE);
    offset = number << 1;

#ifdef PCRE_DEBUG
    printf("start bracket %d\n", number);
    printf("subject=");
    pchars(eptr, 16, TRUE, md);
    printf("\n");
#endif

    if (offset < md->offset_max)
      {
      save_offset1 = md->offset_vector[offset];
      save_offset2 = md->offset_vector[offset+1];
      save_offset3 = md->offset_vector[md->offset_end - number];
      save_capture_last = md->capture_last;
      save_mark = md->mark;

      DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
      md->offset_vector[md->offset_end - number] =
        (int)(eptr - md->start_subject);

      for (;;)
        {
        if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
        RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
          eptrb, RM1);
        if (rrc == MATCH_ONCE) break;  /* Backing up through an atomic group */

        /* If we backed up to a THEN, check whether it is within the current
        branch by comparing the address of the THEN that is passed back with
        the end of the branch. If it is within the current branch, and the
        branch is one of two or more alternatives (it either starts or ends
        with OP_ALT), we have reached the limit of THEN's action, so convert
        the return code to NOMATCH, which will cause normal backtracking to
        happen from now on. Otherwise, THEN is passed back to an outer
        alternative. This implements Perl's treatment of parenthesized groups,
        where a group not containing | does not affect the current alternative,
        that is, (X) is NOT the same as (X|(*F)). */

        if (rrc == MATCH_THEN)
          {
          next = ecode + GET(ecode,1);
          if (md->start_match_ptr < next &&
              (*ecode == OP_ALT || *next == OP_ALT))
            rrc = MATCH_NOMATCH;
          }

        /* Anything other than NOMATCH is passed back. */

        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        md->capture_last = save_capture_last;
        ecode += GET(ecode, 1);
        md->mark = save_mark;
        if (*ecode != OP_ALT) break;
        }

      DPRINTF(("bracket %d failed\n", number));
      md->offset_vector[offset] = save_offset1;
      md->offset_vector[offset+1] = save_offset2;
      md->offset_vector[md->offset_end - number] = save_offset3;

      /* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */

      RRETURN(rrc);
      }

    /* FALL THROUGH ... Insufficient room for saving captured contents. Treat
    as a non-capturing bracket. */

    /* VVVVVVVVVVVVVVVVVVVVVVVVV */
    /* VVVVVVVVVVVVVVVVVVVVVVVVV */

    DPRINTF(("insufficient capture room: treat as non-capturing\n"));

    /* VVVVVVVVVVVVVVVVVVVVVVVVV */
    /* VVVVVVVVVVVVVVVVVVVVVVVVV */

    /* Non-capturing or atomic group, except for possessive with unlimited
    repeat and ONCE group with no captures. Loop for all the alternatives.

    When we get to the final alternative within the brackets, we used to return
    the result of a recursive call to match() whatever happened so it was
    possible to reduce stack usage by turning this into a tail recursion,
    except in the case of a possibly empty group. However, now that there is
    the possiblity of (*THEN) occurring in the final alternative, this
    optimization is no longer always possible.

    We can optimize if we know there are no (*THEN)s in the pattern; at present
    this is the best that can be done.

    MATCH_ONCE is returned when the end of an atomic group is successfully
    reached, but subsequent matching fails. It passes back up the tree (causing
    captured values to be reset) until the original atomic group level is
    reached. This is tested by comparing md->once_target with the start of the
    group. At this point, the return is converted into MATCH_NOMATCH so that
    previous backup points can be taken. */

    case OP_ONCE:
    case OP_BRA:
    case OP_SBRA:
    DPRINTF(("start non-capturing bracket\n"));

    for (;;)
      {
      if (op >= OP_SBRA || op == OP_ONCE)
        md->match_function_type = MATCH_CBEGROUP;

      /* If this is not a possibly empty group, and there are no (*THEN)s in
      the pattern, and this is the final alternative, optimize as described
      above. */

      else if (!md->hasthen && ecode[GET(ecode, 1)] != OP_ALT)
        {
        ecode += PRIV(OP_lengths)[*ecode];
        goto TAIL_RECURSE;
        }

      /* In all other cases, we have to make another call to match(). */

      save_mark = md->mark;
      RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb,
        RM2);

      /* See comment in the code for capturing groups above about handling
      THEN. */

      if (rrc == MATCH_THEN)
        {
        next = ecode + GET(ecode,1);
        if (md->start_match_ptr < next &&
            (*ecode == OP_ALT || *next == OP_ALT))
          rrc = MATCH_NOMATCH;
        }

      if (rrc != MATCH_NOMATCH)
        {
        if (rrc == MATCH_ONCE)
          {
          const pcre_uchar *scode = ecode;
          if (*scode != OP_ONCE)           /* If not at start, find it */
            {
            while (*scode == OP_ALT) scode += GET(scode, 1);
            scode -= GET(scode, 1);
            }
          if (md->once_target == scode) rrc = MATCH_NOMATCH;
          }
        RRETURN(rrc);
        }
      ecode += GET(ecode, 1);
      md->mark = save_mark;
      if (*ecode != OP_ALT) break;
      }

    RRETURN(MATCH_NOMATCH);

    /* Handle possessive capturing brackets with an unlimited repeat. We come
    here from BRAZERO with allow_zero set TRUE. The offset_vector values are
    handled similarly to the normal case above. However, the matching is
    different. The end of these brackets will always be OP_KETRPOS, which
    returns MATCH_KETRPOS without going further in the pattern. By this means
    we can handle the group by iteration rather than recursion, thereby
    reducing the amount of stack needed. */

    case OP_CBRAPOS:
    case OP_SCBRAPOS:
    allow_zero = FALSE;

    POSSESSIVE_CAPTURE:
    number = GET2(ecode, 1+LINK_SIZE);
    offset = number << 1;

#ifdef PCRE_DEBUG
    printf("start possessive bracket %d\n", number);
    printf("subject=");
    pchars(eptr, 16, TRUE, md);
    printf("\n");
#endif

    if (offset < md->offset_max)
      {
      matched_once = FALSE;
      code_offset = (int)(ecode - md->start_code);

      save_offset1 = md->offset_vector[offset];
      save_offset2 = md->offset_vector[offset+1];
      save_offset3 = md->offset_vector[md->offset_end - number];
      save_capture_last = md->capture_last;

      DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));

      /* Each time round the loop, save the current subject position for use
      when the group matches. For MATCH_MATCH, the group has matched, so we
      restart it with a new subject starting position, remembering that we had
      at least one match. For MATCH_NOMATCH, carry on with the alternatives, as
      usual. If we haven't matched any alternatives in any iteration, check to
      see if a previous iteration matched. If so, the group has matched;
      continue from afterwards. Otherwise it has failed; restore the previous
      capture values before returning NOMATCH. */

      for (;;)
        {
        md->offset_vector[md->offset_end - number] =
          (int)(eptr - md->start_subject);
        if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
        RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
          eptrb, RM63);
        if (rrc == MATCH_KETRPOS)
          {
          offset_top = md->end_offset_top;
          eptr = md->end_match_ptr;
          ecode = md->start_code + code_offset;
          save_capture_last = md->capture_last;
          matched_once = TRUE;
          continue;
          }

        /* See comment in the code for capturing groups above about handling
        THEN. */

        if (rrc == MATCH_THEN)
          {
          next = ecode + GET(ecode,1);
          if (md->start_match_ptr < next &&
              (*ecode == OP_ALT || *next == OP_ALT))
            rrc = MATCH_NOMATCH;
          }

        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        md->capture_last = save_capture_last;
        ecode += GET(ecode, 1);
        if (*ecode != OP_ALT) break;
        }

      if (!matched_once)
        {
        md->offset_vector[offset] = save_offset1;
        md->offset_vector[offset+1] = save_offset2;
        md->offset_vector[md->offset_end - number] = save_offset3;
        }

      if (allow_zero || matched_once)
        {
        ecode += 1 + LINK_SIZE;
        break;
        }

      RRETURN(MATCH_NOMATCH);
      }

    /* FALL THROUGH ... Insufficient room for saving captured contents. Treat
    as a non-capturing bracket. */

    /* VVVVVVVVVVVVVVVVVVVVVVVVV */
    /* VVVVVVVVVVVVVVVVVVVVVVVVV */

    DPRINTF(("insufficient capture room: treat as non-capturing\n"));

    /* VVVVVVVVVVVVVVVVVVVVVVVVV */
    /* VVVVVVVVVVVVVVVVVVVVVVVVV */

    /* Non-capturing possessive bracket with unlimited repeat. We come here
    from BRAZERO with allow_zero = TRUE. The code is similar to the above,
    without the capturing complication. It is written out separately for speed
    and cleanliness. */

    case OP_BRAPOS:
    case OP_SBRAPOS:
    allow_zero = FALSE;

    POSSESSIVE_NON_CAPTURE:
    matched_once = FALSE;
    code_offset = (int)(ecode - md->start_code);

    for (;;)
      {
      if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
      RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
        eptrb, RM48);
      if (rrc == MATCH_KETRPOS)
        {
        offset_top = md->end_offset_top;
        eptr = md->end_match_ptr;
        ecode = md->start_code + code_offset;
        matched_once = TRUE;
        continue;
        }

      /* See comment in the code for capturing groups above about handling
      THEN. */

      if (rrc == MATCH_THEN)
        {
        next = ecode + GET(ecode,1);
        if (md->start_match_ptr < next &&
            (*ecode == OP_ALT || *next == OP_ALT))
          rrc = MATCH_NOMATCH;
        }

      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      ecode += GET(ecode, 1);
      if (*ecode != OP_ALT) break;
      }

    if (matched_once || allow_zero)
      {
      ecode += 1 + LINK_SIZE;
      break;
      }
    RRETURN(MATCH_NOMATCH);

    /* Control never reaches here. */

    /* Conditional group: compilation checked that there are no more than
    two branches. If the condition is false, skipping the first branch takes us
    past the end if there is only one branch, but that's OK because that is
    exactly what going to the ket would do. */

    case OP_COND:
    case OP_SCOND:
    codelink = GET(ecode, 1);

    /* Because of the way auto-callout works during compile, a callout item is
    inserted between OP_COND and an assertion condition. */

    if (ecode[LINK_SIZE+1] == OP_CALLOUT)
      {
      if (PUBL(callout) != NULL)
        {
        PUBL(callout_block) cb;
        cb.version          = 2;   /* Version 1 of the callout block */
        cb.callout_number   = ecode[LINK_SIZE+2];
        cb.offset_vector    = md->offset_vector;
#ifdef COMPILE_PCRE8
        cb.subject          = (PCRE_SPTR)md->start_subject;
#else
        cb.subject          = (PCRE_SPTR16)md->start_subject;
#endif
        cb.subject_length   = (int)(md->end_subject - md->start_subject);
        cb.start_match      = (int)(mstart - md->start_subject);
        cb.current_position = (int)(eptr - md->start_subject);
        cb.pattern_position = GET(ecode, LINK_SIZE + 3);
        cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE);
        cb.capture_top      = offset_top/2;
        cb.capture_last     = md->capture_last;
        cb.callout_data     = md->callout_data;
        cb.mark             = md->nomatch_mark;
        if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
        if (rrc < 0) RRETURN(rrc);
        }
      ecode += PRIV(OP_lengths)[OP_CALLOUT];
      }

    condcode = ecode[LINK_SIZE+1];

    /* Now see what the actual condition is */

    if (condcode == OP_RREF || condcode == OP_NRREF)    /* Recursion test */
      {
      if (md->recursive == NULL)                /* Not recursing => FALSE */
        {
        condition = FALSE;
        ecode += GET(ecode, 1);
        }
      else
        {
        int recno = GET2(ecode, LINK_SIZE + 2);   /* Recursion group number*/
        condition = (recno == RREF_ANY || recno == md->recursive->group_num);

        /* If the test is for recursion into a specific subpattern, and it is
        false, but the test was set up by name, scan the table to see if the
        name refers to any other numbers, and test them. The condition is true
        if any one is set. */

        if (!condition && condcode == OP_NRREF)
          {
          pcre_uchar *slotA = md->name_table;
          for (i = 0; i < md->name_count; i++)
            {
            if (GET2(slotA, 0) == recno) break;
            slotA += md->name_entry_size;
            }

          /* Found a name for the number - there can be only one; duplicate
          names for different numbers are allowed, but not vice versa. First
          scan down for duplicates. */

          if (i < md->name_count)
            {
            pcre_uchar *slotB = slotA;
            while (slotB > md->name_table)
              {
              slotB -= md->name_entry_size;
              if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
                {
                condition = GET2(slotB, 0) == md->recursive->group_num;
                if (condition) break;
                }
              else break;
              }

            /* Scan up for duplicates */

            if (!condition)
              {
              slotB = slotA;
              for (i++; i < md->name_count; i++)
                {
                slotB += md->name_entry_size;
                if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
                  {
                  condition = GET2(slotB, 0) == md->recursive->group_num;
                  if (condition) break;
                  }
                else break;
                }
              }
            }
          }

        /* Chose branch according to the condition */

        ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1);
        }
      }

    else if (condcode == OP_CREF || condcode == OP_NCREF)  /* Group used test */
      {
      offset = GET2(ecode, LINK_SIZE+2) << 1;  /* Doubled ref number */
      condition = offset < offset_top && md->offset_vector[offset] >= 0;

      /* If the numbered capture is unset, but the reference was by name,
      scan the table to see if the name refers to any other numbers, and test
      them. The condition is true if any one is set. This is tediously similar
      to the code above, but not close enough to try to amalgamate. */

      if (!condition && condcode == OP_NCREF)
        {
        int refno = offset >> 1;
        pcre_uchar *slotA = md->name_table;

        for (i = 0; i < md->name_count; i++)
          {
          if (GET2(slotA, 0) == refno) break;
          slotA += md->name_entry_size;
          }

        /* Found a name for the number - there can be only one; duplicate names
        for different numbers are allowed, but not vice versa. First scan down
        for duplicates. */

        if (i < md->name_count)
          {
          pcre_uchar *slotB = slotA;
          while (slotB > md->name_table)
            {
            slotB -= md->name_entry_size;
            if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
              {
              offset = GET2(slotB, 0) << 1;
              condition = offset < offset_top &&
                md->offset_vector[offset] >= 0;
              if (condition) break;
              }
            else break;
            }

          /* Scan up for duplicates */

          if (!condition)
            {
            slotB = slotA;
            for (i++; i < md->name_count; i++)
              {
              slotB += md->name_entry_size;
              if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
                {
                offset = GET2(slotB, 0) << 1;
                condition = offset < offset_top &&
                  md->offset_vector[offset] >= 0;
                if (condition) break;
                }
              else break;
              }
            }
          }
        }

      /* Chose branch according to the condition */

      ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1);
      }

    else if (condcode == OP_DEF)     /* DEFINE - always false */
      {
      condition = FALSE;
      ecode += GET(ecode, 1);
      }

    /* The condition is an assertion. Call match() to evaluate it - setting
    md->match_function_type to MATCH_CONDASSERT causes it to stop at the end of
    an assertion. */

    else
      {
      md->match_function_type = MATCH_CONDASSERT;
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM3);
      if (rrc == MATCH_MATCH)
        {
        if (md->end_offset_top > offset_top)
          offset_top = md->end_offset_top;  /* Captures may have happened */
        condition = TRUE;
        ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2);
        while (*ecode == OP_ALT) ecode += GET(ecode, 1);
        }

      /* PCRE doesn't allow the effect of (*THEN) to escape beyond an
      assertion; it is therefore treated as NOMATCH. */

      else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
        {
        RRETURN(rrc);         /* Need braces because of following else */
        }
      else
        {
        condition = FALSE;
        ecode += codelink;
        }
      }

    /* We are now at the branch that is to be obeyed. As there is only one, can
    use tail recursion to avoid using another stack frame, except when there is
    unlimited repeat of a possibly empty group. In the latter case, a recursive
    call to match() is always required, unless the second alternative doesn't
    exist, in which case we can just plough on. Note that, for compatibility
    with Perl, the | in a conditional group is NOT treated as creating two
    alternatives. If a THEN is encountered in the branch, it propagates out to
    the enclosing alternative (unless nested in a deeper set of alternatives,
    of course). */

    if (condition || *ecode == OP_ALT)
      {
      if (op != OP_SCOND)
        {
        ecode += 1 + LINK_SIZE;
        goto TAIL_RECURSE;
        }

      md->match_function_type = MATCH_CBEGROUP;
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM49);
      RRETURN(rrc);
      }

     /* Condition false & no alternative; continue after the group. */

    else
      {
      ecode += 1 + LINK_SIZE;
      }
    break;


    /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes,
    to close any currently open capturing brackets. */

    case OP_CLOSE:
    number = GET2(ecode, 1);
    offset = number << 1;

#ifdef PCRE_DEBUG
      printf("end bracket %d at *ACCEPT", number);
      printf("\n");
#endif

    md->capture_last = number;
    if (offset >= md->offset_max) md->offset_overflow = TRUE; else
      {
      md->offset_vector[offset] =
        md->offset_vector[md->offset_end - number];
      md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
      if (offset_top <= offset) offset_top = offset + 2;
      }
    ecode += 1 + IMM2_SIZE;
    break;


    /* End of the pattern, either real or forced. */

    case OP_END:
    case OP_ACCEPT:
    case OP_ASSERT_ACCEPT:

    /* If we have matched an empty string, fail if not in an assertion and not
    in a recursion if either PCRE_NOTEMPTY is set, or if PCRE_NOTEMPTY_ATSTART
    is set and we have matched at the start of the subject. In both cases,
    backtracking will then try other alternatives, if any. */

    if (eptr == mstart && op != OP_ASSERT_ACCEPT &&
         md->recursive == NULL &&
         (md->notempty ||
           (md->notempty_atstart &&
             mstart == md->start_subject + md->start_offset)))
      RRETURN(MATCH_NOMATCH);

    /* Otherwise, we have a match. */

    md->end_match_ptr = eptr;           /* Record where we ended */
    md->end_offset_top = offset_top;    /* and how many extracts were taken */
    md->start_match_ptr = mstart;       /* and the start (\K can modify) */

    /* For some reason, the macros don't work properly if an expression is
    given as the argument to RRETURN when the heap is in use. */

    rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT;
    RRETURN(rrc);

    /* Assertion brackets. Check the alternative branches in turn - the
    matching won't pass the KET for an assertion. If any one branch matches,
    the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
    start of each branch to move the current point backwards, so the code at
    this level is identical to the lookahead case. When the assertion is part
    of a condition, we want to return immediately afterwards. The caller of
    this incarnation of the match() function will have set MATCH_CONDASSERT in
    md->match_function type, and one of these opcodes will be the first opcode
    that is processed. We use a local variable that is preserved over calls to
    match() to remember this case. */

    case OP_ASSERT:
    case OP_ASSERTBACK:
    save_mark = md->mark;
    if (md->match_function_type == MATCH_CONDASSERT)
      {
      condassert = TRUE;
      md->match_function_type = 0;
      }
    else condassert = FALSE;

    do
      {
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);
      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
        {
        mstart = md->start_match_ptr;   /* In case \K reset it */
        break;
        }
      md->mark = save_mark;

      /* A COMMIT failure must fail the entire assertion, without trying any
      subsequent branches. */

      if (rrc == MATCH_COMMIT) RRETURN(MATCH_NOMATCH);

      /* PCRE does not allow THEN to escape beyond an assertion; it
      is treated as NOMATCH. */

      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
      ecode += GET(ecode, 1);
      }
    while (*ecode == OP_ALT);

    if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);

    /* If checking an assertion for a condition, return MATCH_MATCH. */

    if (condassert) RRETURN(MATCH_MATCH);

    /* Continue from after the assertion, updating the offsets high water
    mark, since extracts may have been taken during the assertion. */

    do ecode += GET(ecode,1); while (*ecode == OP_ALT);
    ecode += 1 + LINK_SIZE;
    offset_top = md->end_offset_top;
    continue;

    /* Negative assertion: all branches must fail to match. Encountering SKIP,
    PRUNE, or COMMIT means we must assume failure without checking subsequent
    branches. */

    case OP_ASSERT_NOT:
    case OP_ASSERTBACK_NOT:
    save_mark = md->mark;
    if (md->match_function_type == MATCH_CONDASSERT)
      {
      condassert = TRUE;
      md->match_function_type = 0;
      }
    else condassert = FALSE;

    do
      {
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);
      md->mark = save_mark;
      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) RRETURN(MATCH_NOMATCH);
      if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT)
        {
        do ecode += GET(ecode,1); while (*ecode == OP_ALT);
        break;
        }

      /* PCRE does not allow THEN to escape beyond an assertion; it is treated
      as NOMATCH. */

      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
      ecode += GET(ecode,1);
      }
    while (*ecode == OP_ALT);

    if (condassert) RRETURN(MATCH_MATCH);  /* Condition assertion */

    ecode += 1 + LINK_SIZE;
    continue;

    /* Move the subject pointer back. This occurs only at the start of
    each branch of a lookbehind assertion. If we are too close to the start to
    move back, this match function fails. When working with UTF-8 we move
    back a number of characters, not bytes. */

    case OP_REVERSE:
#ifdef SUPPORT_UTF
    if (utf)
      {
      i = GET(ecode, 1);
      while (i-- > 0)
        {
        eptr--;
        if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
        BACKCHAR(eptr);
        }
      }
    else
#endif

    /* No UTF-8 support, or not in UTF-8 mode: count is byte count */

      {
      eptr -= GET(ecode, 1);
      if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
      }

    /* Save the earliest consulted character, then skip to next op code */

    if (eptr < md->start_used_ptr) md->start_used_ptr = eptr;
    ecode += 1 + LINK_SIZE;
    break;

    /* The callout item calls an external function, if one is provided, passing
    details of the match so far. This is mainly for debugging, though the
    function is able to force a failure. */

    case OP_CALLOUT:
    if (PUBL(callout) != NULL)
      {
      PUBL(callout_block) cb;
      cb.version          = 2;   /* Version 1 of the callout block */
      cb.callout_number   = ecode[1];
      cb.offset_vector    = md->offset_vector;
#ifdef COMPILE_PCRE8
      cb.subject          = (PCRE_SPTR)md->start_subject;
#else
      cb.subject          = (PCRE_SPTR16)md->start_subject;
#endif
      cb.subject_length   = (int)(md->end_subject - md->start_subject);
      cb.start_match      = (int)(mstart - md->start_subject);
      cb.current_position = (int)(eptr - md->start_subject);
      cb.pattern_position = GET(ecode, 2);
      cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
      cb.capture_top      = offset_top/2;
      cb.capture_last     = md->capture_last;
      cb.callout_data     = md->callout_data;
      cb.mark             = md->nomatch_mark;
      if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
      if (rrc < 0) RRETURN(rrc);
      }
    ecode += 2 + 2*LINK_SIZE;
    break;

    /* Recursion either matches the current regex, or some subexpression. The
    offset data is the offset to the starting bracket from the start of the
    whole pattern. (This is so that it works from duplicated subpatterns.)

    The state of the capturing groups is preserved over recursion, and
    re-instated afterwards. We don't know how many are started and not yet
    finished (offset_top records the completed total) so we just have to save
    all the potential data. There may be up to 65535 such values, which is too
    large to put on the stack, but using malloc for small numbers seems
    expensive. As a compromise, the stack is used when there are no more than
    REC_STACK_SAVE_MAX values to store; otherwise malloc is used.

    There are also other values that have to be saved. We use a chained
    sequence of blocks that actually live on the stack. Thanks to Robin Houston
    for the original version of this logic. It has, however, been hacked around
    a lot, so he is not to blame for the current way it works. */

    case OP_RECURSE:
      {
      recursion_info *ri;
      int recno;

      callpat = md->start_code + GET(ecode, 1);
      recno = (callpat == md->start_code)? 0 :
        GET2(callpat, 1 + LINK_SIZE);

      /* Check for repeating a recursion without advancing the subject pointer.
      This should catch convoluted mutual recursions. (Some simple cases are
      caught at compile time.) */

      for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
        if (recno == ri->group_num && eptr == ri->subject_position)
          RRETURN(PCRE_ERROR_RECURSELOOP);

      /* Add to "recursing stack" */

      new_recursive.group_num = recno;
      new_recursive.subject_position = eptr;
      new_recursive.prevrec = md->recursive;
      md->recursive = &new_recursive;

      /* Where to continue from afterwards */

      ecode += 1 + LINK_SIZE;

      /* Now save the offset data */

      new_recursive.saved_max = md->offset_end;
      if (new_recursive.saved_max <= REC_STACK_SAVE_MAX)
        new_recursive.offset_save = stacksave;
      else
        {
        new_recursive.offset_save =
          (int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int));
        if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
        }
      memcpy(new_recursive.offset_save, md->offset_vector,
            new_recursive.saved_max * sizeof(int));

      /* OK, now we can do the recursion. After processing each alternative,
      restore the offset data. If there were nested recursions, md->recursive
      might be changed, so reset it before looping. */

      DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
      cbegroup = (*callpat >= OP_SBRA);
      do
        {
        if (cbegroup) md->match_function_type = MATCH_CBEGROUP;
        RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top,
          md, eptrb, RM6);
        memcpy(md->offset_vector, new_recursive.offset_save,
            new_recursive.saved_max * sizeof(int));
        md->recursive = new_recursive.prevrec;
        if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
          {
          DPRINTF(("Recursion matched\n"));
          if (new_recursive.offset_save != stacksave)
            (PUBL(free))(new_recursive.offset_save);

          /* Set where we got to in the subject, and reset the start in case
          it was changed by \K. This *is* propagated back out of a recursion,
          for Perl compatibility. */

          eptr = md->end_match_ptr;
          mstart = md->start_match_ptr;
          goto RECURSION_MATCHED;        /* Exit loop; end processing */
          }

        /* PCRE does not allow THEN or COMMIT to escape beyond a recursion; it
        is treated as NOMATCH. */

        else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN &&
                 rrc != MATCH_COMMIT)
          {
          DPRINTF(("Recursion gave error %d\n", rrc));
          if (new_recursive.offset_save != stacksave)
            (PUBL(free))(new_recursive.offset_save);
          RRETURN(rrc);
          }

        md->recursive = &new_recursive;
        callpat += GET(callpat, 1);
        }
      while (*callpat == OP_ALT);

      DPRINTF(("Recursion didn't match\n"));
      md->recursive = new_recursive.prevrec;
      if (new_recursive.offset_save != stacksave)
        (PUBL(free))(new_recursive.offset_save);
      RRETURN(MATCH_NOMATCH);
      }

    RECURSION_MATCHED:
    break;

    /* An alternation is the end of a branch; scan along to find the end of the
    bracketed group and go to there. */

    case OP_ALT:
    do ecode += GET(ecode,1); while (*ecode == OP_ALT);
    break;

    /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group,
    indicating that it may occur zero times. It may repeat infinitely, or not
    at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets
    with fixed upper repeat limits are compiled as a number of copies, with the
    optional ones preceded by BRAZERO or BRAMINZERO. */

    case OP_BRAZERO:
    next = ecode + 1;
    RMATCH(eptr, next, offset_top, md, eptrb, RM10);
    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
    do next += GET(next, 1); while (*next == OP_ALT);
    ecode = next + 1 + LINK_SIZE;
    break;

    case OP_BRAMINZERO:
    next = ecode + 1;
    do next += GET(next, 1); while (*next == OP_ALT);
    RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, RM11);
    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
    ecode++;
    break;

    case OP_SKIPZERO:
    next = ecode+1;
    do next += GET(next,1); while (*next == OP_ALT);
    ecode = next + 1 + LINK_SIZE;
    break;

    /* BRAPOSZERO occurs before a possessive bracket group. Don't do anything
    here; just jump to the group, with allow_zero set TRUE. */

    case OP_BRAPOSZERO:
    op = *(++ecode);
    allow_zero = TRUE;
    if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE;
      goto POSSESSIVE_NON_CAPTURE;

    /* End of a group, repeated or non-repeating. */

    case OP_KET:
    case OP_KETRMIN:
    case OP_KETRMAX:
    case OP_KETRPOS:
    prev = ecode - GET(ecode, 1);

    /* If this was a group that remembered the subject start, in order to break
    infinite repeats of empty string matches, retrieve the subject start from
    the chain. Otherwise, set it NULL. */

    if (*prev >= OP_SBRA || *prev == OP_ONCE)
      {
      saved_eptr = eptrb->epb_saved_eptr;   /* Value at start of group */
      eptrb = eptrb->epb_prev;              /* Backup to previous group */
      }
    else saved_eptr = NULL;

    /* If we are at the end of an assertion group or a non-capturing atomic
    group, stop matching and return MATCH_MATCH, but record the current high
    water mark for use by positive assertions. We also need to record the match
    start in case it was changed by \K. */

    if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) ||
         *prev == OP_ONCE_NC)
      {
      md->end_match_ptr = eptr;      /* For ONCE_NC */
      md->end_offset_top = offset_top;
      md->start_match_ptr = mstart;
      RRETURN(MATCH_MATCH);         /* Sets md->mark */
      }

    /* For capturing groups we have to check the group number back at the start
    and if necessary complete handling an extraction by setting the offsets and
    bumping the high water mark. Whole-pattern recursion is coded as a recurse
    into group 0, so it won't be picked up here. Instead, we catch it when the
    OP_END is reached. Other recursion is handled here. We just have to record
    the current subject position and start match pointer and give a MATCH
    return. */

    if (*prev == OP_CBRA || *prev == OP_SCBRA ||
        *prev == OP_CBRAPOS || *prev == OP_SCBRAPOS)
      {
      number = GET2(prev, 1+LINK_SIZE);
      offset = number << 1;

#ifdef PCRE_DEBUG
      printf("end bracket %d", number);
      printf("\n");
#endif

      /* Handle a recursively called group. */

      if (md->recursive != NULL && md->recursive->group_num == number)
        {
        md->end_match_ptr = eptr;
        md->start_match_ptr = mstart;
        RRETURN(MATCH_MATCH);
        }

      /* Deal with capturing */

      md->capture_last = number;
      if (offset >= md->offset_max) md->offset_overflow = TRUE; else
        {
        /* If offset is greater than offset_top, it means that we are
        "skipping" a capturing group, and that group's offsets must be marked
        unset. In earlier versions of PCRE, all the offsets were unset at the
        start of matching, but this doesn't work because atomic groups and
        assertions can cause a value to be set that should later be unset.
        Example: matching /(?>(a))b|(a)c/ against "ac". This sets group 1 as
        part of the atomic group, but this is not on the final matching path,
        so must be unset when 2 is set. (If there is no group 2, there is no
        problem, because offset_top will then be 2, indicating no capture.) */

        if (offset > offset_top)
          {
          register int *iptr = md->offset_vector + offset_top;
          register int *iend = md->offset_vector + offset;
          while (iptr < iend) *iptr++ = -1;
          }

        /* Now make the extraction */

        md->offset_vector[offset] =
          md->offset_vector[md->offset_end - number];
        md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
        if (offset_top <= offset) offset_top = offset + 2;
        }
      }

    /* For an ordinary non-repeating ket, just continue at this level. This
    also happens for a repeating ket if no characters were matched in the
    group. This is the forcible breaking of infinite loops as implemented in
    Perl 5.005. For a non-repeating atomic group that includes captures,
    establish a backup point by processing the rest of the pattern at a lower
    level. If this results in a NOMATCH return, pass MATCH_ONCE back to the
    original OP_ONCE level, thereby bypassing intermediate backup points, but
    resetting any captures that happened along the way. */

    if (*ecode == OP_KET || eptr == saved_eptr)
      {
      if (*prev == OP_ONCE)
        {
        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12);
        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        md->once_target = prev;  /* Level at which to change to MATCH_NOMATCH */
        RRETURN(MATCH_ONCE);
        }
      ecode += 1 + LINK_SIZE;    /* Carry on at this level */
      break;
      }

    /* OP_KETRPOS is a possessive repeating ket. Remember the current position,
    and return the MATCH_KETRPOS. This makes it possible to do the repeats one
    at a time from the outer level, thus saving stack. */

    if (*ecode == OP_KETRPOS)
      {
      md->end_match_ptr = eptr;
      md->end_offset_top = offset_top;
      RRETURN(MATCH_KETRPOS);
      }

    /* The normal repeating kets try the rest of the pattern or restart from
    the preceding bracket, in the appropriate order. In the second case, we can
    use tail recursion to avoid using another stack frame, unless we have an
    an atomic group or an unlimited repeat of a group that can match an empty
    string. */

    if (*ecode == OP_KETRMIN)
      {
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7);
      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      if (*prev == OP_ONCE)
        {
        RMATCH(eptr, prev, offset_top, md, eptrb, RM8);
        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        md->once_target = prev;  /* Level at which to change to MATCH_NOMATCH */
        RRETURN(MATCH_ONCE);
        }
      if (*prev >= OP_SBRA)    /* Could match an empty string */
        {
        RMATCH(eptr, prev, offset_top, md, eptrb, RM50);
        RRETURN(rrc);
        }
      ecode = prev;
      goto TAIL_RECURSE;
      }
    else  /* OP_KETRMAX */
      {
      RMATCH(eptr, prev, offset_top, md, eptrb, RM13);
      if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH;
      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      if (*prev == OP_ONCE)
        {
        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM9);
        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        md->once_target = prev;
        RRETURN(MATCH_ONCE);
        }
      ecode += 1 + LINK_SIZE;
      goto TAIL_RECURSE;
      }
    /* Control never gets here */

    /* Not multiline mode: start of subject assertion, unless notbol. */

    case OP_CIRC:
    if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);

    /* Start of subject assertion */

    case OP_SOD:
    if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    /* Multiline mode: start of subject unless notbol, or after any newline. */

    case OP_CIRCM:
    if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
    if (eptr != md->start_subject &&
        (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    /* Start of match assertion */

    case OP_SOM:
    if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    /* Reset the start of match point */

    case OP_SET_SOM:
    mstart = eptr;
    ecode++;
    break;

    /* Multiline mode: assert before any newline, or before end of subject
    unless noteol is set. */

    case OP_DOLLM:
    if (eptr < md->end_subject)
      {
      if (!IS_NEWLINE(eptr))
        {
        if (md->partial != 0 &&
            eptr + 1 >= md->end_subject &&
            NLBLOCK->nltype == NLTYPE_FIXED &&
            NLBLOCK->nllen == 2 &&
            *eptr == NLBLOCK->nl[0])
          {
          md->hitend = TRUE;
          if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
          }
        RRETURN(MATCH_NOMATCH);
        }
      }
    else
      {
      if (md->noteol) RRETURN(MATCH_NOMATCH);
      SCHECK_PARTIAL();
      }
    ecode++;
    break;

    /* Not multiline mode: assert before a terminating newline or before end of
    subject unless noteol is set. */

    case OP_DOLL:
    if (md->noteol) RRETURN(MATCH_NOMATCH);
    if (!md->endonly) goto ASSERT_NL_OR_EOS;

    /* ... else fall through for endonly */

    /* End of subject assertion (\z) */

    case OP_EOD:
    if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);
    SCHECK_PARTIAL();
    ecode++;
    break;

    /* End of subject or ending \n assertion (\Z) */

    case OP_EODN:
    ASSERT_NL_OR_EOS:
    if (eptr < md->end_subject &&
        (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
      {
      if (md->partial != 0 &&
          eptr + 1 >= md->end_subject &&
          NLBLOCK->nltype == NLTYPE_FIXED &&
          NLBLOCK->nllen == 2 &&
          *eptr == NLBLOCK->nl[0])
        {
        md->hitend = TRUE;
        if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
        }
      RRETURN(MATCH_NOMATCH);
      }

    /* Either at end of string or \n before end. */

    SCHECK_PARTIAL();
    ecode++;
    break;

    /* Word boundary assertions */

    case OP_NOT_WORD_BOUNDARY:
    case OP_WORD_BOUNDARY:
      {

      /* Find out if the previous and current characters are "word" characters.
      It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to
      be "non-word" characters. Remember the earliest consulted character for
      partial matching. */

#ifdef SUPPORT_UTF
      if (utf)
        {
        /* Get status of previous character */

        if (eptr == md->start_subject) prev_is_word = FALSE; else
          {
          PCRE_PUCHAR lastptr = eptr - 1;
          BACKCHAR(lastptr);
          if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
          GETCHAR(c, lastptr);
#ifdef SUPPORT_UCP
          if (md->use_ucp)
            {
            if (c == '_') prev_is_word = TRUE; else
              {
              int cat = UCD_CATEGORY(c);
              prev_is_word = (cat == ucp_L || cat == ucp_N);
              }
            }
          else
#endif
          prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
          }

        /* Get status of next character */

        if (eptr >= md->end_subject)
          {
          SCHECK_PARTIAL();
          cur_is_word = FALSE;
          }
        else
          {
          GETCHAR(c, eptr);
#ifdef SUPPORT_UCP
          if (md->use_ucp)
            {
            if (c == '_') cur_is_word = TRUE; else
              {
              int cat = UCD_CATEGORY(c);
              cur_is_word = (cat == ucp_L || cat == ucp_N);
              }
            }
          else
#endif
          cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
          }
        }
      else
#endif

      /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for
      consistency with the behaviour of \w we do use it in this case. */

        {
        /* Get status of previous character */

        if (eptr == md->start_subject) prev_is_word = FALSE; else
          {
          if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1;
#ifdef SUPPORT_UCP
          if (md->use_ucp)
            {
            c = eptr[-1];
            if (c == '_') prev_is_word = TRUE; else
              {
              int cat = UCD_CATEGORY(c);
              prev_is_word = (cat == ucp_L || cat == ucp_N);
              }
            }
          else
#endif
          prev_is_word = MAX_255(eptr[-1])
            && ((md->ctypes[eptr[-1]] & ctype_word) != 0);
          }

        /* Get status of next character */

        if (eptr >= md->end_subject)
          {
          SCHECK_PARTIAL();
          cur_is_word = FALSE;
          }
        else
#ifdef SUPPORT_UCP
        if (md->use_ucp)
          {
          c = *eptr;
          if (c == '_') cur_is_word = TRUE; else
            {
            int cat = UCD_CATEGORY(c);
            cur_is_word = (cat == ucp_L || cat == ucp_N);
            }
          }
        else
#endif
        cur_is_word = MAX_255(*eptr)
          && ((md->ctypes[*eptr] & ctype_word) != 0);
        }

      /* Now see if the situation is what we want */

      if ((*ecode++ == OP_WORD_BOUNDARY)?
           cur_is_word == prev_is_word : cur_is_word != prev_is_word)
        RRETURN(MATCH_NOMATCH);
      }
    break;

    /* Match any single character type except newline; have to take care with
    CRLF newlines and partial matching. */

    case OP_ANY:
    if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
    if (md->partial != 0 &&
        eptr + 1 >= md->end_subject &&
        NLBLOCK->nltype == NLTYPE_FIXED &&
        NLBLOCK->nllen == 2 &&
        *eptr == NLBLOCK->nl[0])
      {
      md->hitend = TRUE;
      if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
      }

    /* Fall through */

    /* Match any single character whatsoever. */

    case OP_ALLANY:
    if (eptr >= md->end_subject)   /* DO NOT merge the eptr++ here; it must */
      {                            /* not be updated before SCHECK_PARTIAL. */
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    eptr++;
#ifdef SUPPORT_UTF
    if (utf) ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
#endif
    ecode++;
    break;

    /* Match a single byte, even in UTF-8 mode. This opcode really does match
    any byte, even newline, independent of the setting of PCRE_DOTALL. */

    case OP_ANYBYTE:
    if (eptr >= md->end_subject)   /* DO NOT merge the eptr++ here; it must */
      {                            /* not be updated before SCHECK_PARTIAL. */
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    eptr++;
    ecode++;
    break;

    case OP_NOT_DIGIT:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
       c < 256 &&
#endif
       (md->ctypes[c] & ctype_digit) != 0
       )
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    case OP_DIGIT:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
       c > 255 ||
#endif
       (md->ctypes[c] & ctype_digit) == 0
       )
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    case OP_NOT_WHITESPACE:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
       c < 256 &&
#endif
       (md->ctypes[c] & ctype_space) != 0
       )
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    case OP_WHITESPACE:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
       c > 255 ||
#endif
       (md->ctypes[c] & ctype_space) == 0
       )
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    case OP_NOT_WORDCHAR:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
       c < 256 &&
#endif
       (md->ctypes[c] & ctype_word) != 0
       )
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    case OP_WORDCHAR:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
       c > 255 ||
#endif
       (md->ctypes[c] & ctype_word) == 0
       )
      RRETURN(MATCH_NOMATCH);
    ecode++;
    break;

    case OP_ANYNL:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    switch(c)
      {
      default: RRETURN(MATCH_NOMATCH);

      case 0x000d:
      if (eptr >= md->end_subject)
        {
        SCHECK_PARTIAL();
        }
      else if (*eptr == 0x0a) eptr++;
      break;

      case 0x000a:
      break;

      case 0x000b:
      case 0x000c:
      case 0x0085:
      case 0x2028:
      case 0x2029:
      if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
      break;
      }
    ecode++;
    break;

    case OP_NOT_HSPACE:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    switch(c)
      {
      default: break;
      case 0x09:      /* HT */
      case 0x20:      /* SPACE */
      case 0xa0:      /* NBSP */
      case 0x1680:    /* OGHAM SPACE MARK */
      case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
      case 0x2000:    /* EN QUAD */
      case 0x2001:    /* EM QUAD */
      case 0x2002:    /* EN SPACE */
      case 0x2003:    /* EM SPACE */
      case 0x2004:    /* THREE-PER-EM SPACE */
      case 0x2005:    /* FOUR-PER-EM SPACE */
      case 0x2006:    /* SIX-PER-EM SPACE */
      case 0x2007:    /* FIGURE SPACE */
      case 0x2008:    /* PUNCTUATION SPACE */
      case 0x2009:    /* THIN SPACE */
      case 0x200A:    /* HAIR SPACE */
      case 0x202f:    /* NARROW NO-BREAK SPACE */
      case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
      case 0x3000:    /* IDEOGRAPHIC SPACE */
      RRETURN(MATCH_NOMATCH);
      }
    ecode++;
    break;

    case OP_HSPACE:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    switch(c)
      {
      default: RRETURN(MATCH_NOMATCH);
      case 0x09:      /* HT */
      case 0x20:      /* SPACE */
      case 0xa0:      /* NBSP */
      case 0x1680:    /* OGHAM SPACE MARK */
      case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
      case 0x2000:    /* EN QUAD */
      case 0x2001:    /* EM QUAD */
      case 0x2002:    /* EN SPACE */
      case 0x2003:    /* EM SPACE */
      case 0x2004:    /* THREE-PER-EM SPACE */
      case 0x2005:    /* FOUR-PER-EM SPACE */
      case 0x2006:    /* SIX-PER-EM SPACE */
      case 0x2007:    /* FIGURE SPACE */
      case 0x2008:    /* PUNCTUATION SPACE */
      case 0x2009:    /* THIN SPACE */
      case 0x200A:    /* HAIR SPACE */
      case 0x202f:    /* NARROW NO-BREAK SPACE */
      case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
      case 0x3000:    /* IDEOGRAPHIC SPACE */
      break;
      }
    ecode++;
    break;

    case OP_NOT_VSPACE:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    switch(c)
      {
      default: break;
      case 0x0a:      /* LF */
      case 0x0b:      /* VT */
      case 0x0c:      /* FF */
      case 0x0d:      /* CR */
      case 0x85:      /* NEL */
      case 0x2028:    /* LINE SEPARATOR */
      case 0x2029:    /* PARAGRAPH SEPARATOR */
      RRETURN(MATCH_NOMATCH);
      }
    ecode++;
    break;

    case OP_VSPACE:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    switch(c)
      {
      default: RRETURN(MATCH_NOMATCH);
      case 0x0a:      /* LF */
      case 0x0b:      /* VT */
      case 0x0c:      /* FF */
      case 0x0d:      /* CR */
      case 0x85:      /* NEL */
      case 0x2028:    /* LINE SEPARATOR */
      case 0x2029:    /* PARAGRAPH SEPARATOR */
      break;
      }
    ecode++;
    break;

#ifdef SUPPORT_UCP
    /* Check the next character by Unicode property. We will get here only
    if the support is in the binary; otherwise a compile-time error occurs. */

    case OP_PROP:
    case OP_NOTPROP:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
      {
      const ucd_record *prop = GET_UCD(c);

      switch(ecode[1])
        {
        case PT_ANY:
        if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
        break;

        case PT_LAMP:
        if ((prop->chartype == ucp_Lu ||
             prop->chartype == ucp_Ll ||
             prop->chartype == ucp_Lt) == (op == OP_NOTPROP))
          RRETURN(MATCH_NOMATCH);
        break;

        case PT_GC:
        if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP))
          RRETURN(MATCH_NOMATCH);
        break;

        case PT_PC:
        if ((ecode[2] != prop->chartype) == (op == OP_PROP))
          RRETURN(MATCH_NOMATCH);
        break;

        case PT_SC:
        if ((ecode[2] != prop->script) == (op == OP_PROP))
          RRETURN(MATCH_NOMATCH);
        break;

        /* These are specials */

        case PT_ALNUM:
        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
             PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP))
          RRETURN(MATCH_NOMATCH);
        break;

        case PT_SPACE:    /* Perl space */
        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
             c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
               == (op == OP_NOTPROP))
          RRETURN(MATCH_NOMATCH);
        break;

        case PT_PXSPACE:  /* POSIX space */
        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
             c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
             c == CHAR_FF || c == CHAR_CR)
               == (op == OP_NOTPROP))
          RRETURN(MATCH_NOMATCH);
        break;

        case PT_WORD:
        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
             PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
             c == CHAR_UNDERSCORE) == (op == OP_NOTPROP))
          RRETURN(MATCH_NOMATCH);
        break;

        /* This should never occur */

        default:
        RRETURN(PCRE_ERROR_INTERNAL);
        }

      ecode += 3;
      }
    break;

    /* Match an extended Unicode sequence. We will get here only if the support
    is in the binary; otherwise a compile-time error occurs. */

    case OP_EXTUNI:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
    GETCHARINCTEST(c, eptr);
    if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH);
    while (eptr < md->end_subject)
      {
      int len = 1;
      if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
      if (UCD_CATEGORY(c) != ucp_M) break;
      eptr += len;
      }
    CHECK_PARTIAL();
    ecode++;
    break;
#endif


    /* Match a back reference, possibly repeatedly. Look past the end of the
    item to see if there is repeat information following. The code is similar
    to that for character classes, but repeated for efficiency. Then obey
    similar code to character type repeats - written out again for speed.
    However, if the referenced string is the empty string, always treat
    it as matched, any number of times (otherwise there could be infinite
    loops). */

    case OP_REF:
    case OP_REFI:
    caseless = op == OP_REFI;
    offset = GET2(ecode, 1) << 1;               /* Doubled ref number */
    ecode += 1 + IMM2_SIZE;

    /* If the reference is unset, there are two possibilities:

    (a) In the default, Perl-compatible state, set the length negative;
    this ensures that every attempt at a match fails. We can't just fail
    here, because of the possibility of quantifiers with zero minima.

    (b) If the JavaScript compatibility flag is set, set the length to zero
    so that the back reference matches an empty string.

    Otherwise, set the length to the length of what was matched by the
    referenced subpattern. */

    if (offset >= offset_top || md->offset_vector[offset] < 0)
      length = (md->jscript_compat)? 0 : -1;
    else
      length = md->offset_vector[offset+1] - md->offset_vector[offset];

    /* Set up for repetition, or handle the non-repeated case */

    switch (*ecode)
      {
      case OP_CRSTAR:
      case OP_CRMINSTAR:
      case OP_CRPLUS:
      case OP_CRMINPLUS:
      case OP_CRQUERY:
      case OP_CRMINQUERY:
      c = *ecode++ - OP_CRSTAR;
      minimize = (c & 1) != 0;
      min = rep_min[c];                 /* Pick up values from tables; */
      max = rep_max[c];                 /* zero for max => infinity */
      if (max == 0) max = INT_MAX;
      break;

      case OP_CRRANGE:
      case OP_CRMINRANGE:
      minimize = (*ecode == OP_CRMINRANGE);
      min = GET2(ecode, 1);
      max = GET2(ecode, 1 + IMM2_SIZE);
      if (max == 0) max = INT_MAX;
      ecode += 1 + 2 * IMM2_SIZE;
      break;

      default:               /* No repeat follows */
      if ((length = match_ref(offset, eptr, length, md, caseless)) < 0)
        {
        if (length == -2) eptr = md->end_subject;   /* Partial match */
        CHECK_PARTIAL();
        RRETURN(MATCH_NOMATCH);
        }
      eptr += length;
      continue;              /* With the main loop */
      }

    /* Handle repeated back references. If the length of the reference is
    zero, just continue with the main loop. If the length is negative, it
    means the reference is unset in non-Java-compatible mode. If the minimum is
    zero, we can continue at the same level without recursion. For any other
    minimum, carrying on will result in NOMATCH. */

    if (length == 0) continue;
    if (length < 0 && min == 0) continue;

    /* First, ensure the minimum number of matches are present. We get back
    the length of the reference string explicitly rather than passing the
    address of eptr, so that eptr can be a register variable. */

    for (i = 1; i <= min; i++)
      {
      int slength;
      if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
        {
        if (slength == -2) eptr = md->end_subject;   /* Partial match */
        CHECK_PARTIAL();
        RRETURN(MATCH_NOMATCH);
        }
      eptr += slength;
      }

    /* If min = max, continue at the same level without recursion.
    They are not both allowed to be zero. */

    if (min == max) continue;

    /* If minimizing, keep trying and advancing the pointer */

    if (minimize)
      {
      for (fi = min;; fi++)
        {
        int slength;
        RMATCH(eptr, ecode, offset_top, md, eptrb, RM14);
        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        if (fi >= max) RRETURN(MATCH_NOMATCH);
        if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
          {
          if (slength == -2) eptr = md->end_subject;   /* Partial match */
          CHECK_PARTIAL();
          RRETURN(MATCH_NOMATCH);
          }
        eptr += slength;
        }
      /* Control never gets here */
      }

    /* If maximizing, find the longest string and work backwards */

    else
      {
      pp = eptr;
      for (i = min; i < max; i++)
        {
        int slength;
        if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
          {
          /* Can't use CHECK_PARTIAL because we don't want to update eptr in
          the soft partial matching case. */

          if (slength == -2 && md->partial != 0 &&
              md->end_subject > md->start_used_ptr)
            {
            md->hitend = TRUE;
            if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
            }
          break;
          }
        eptr += slength;
        }

      while (eptr >= pp)
        {
        RMATCH(eptr, ecode, offset_top, md, eptrb, RM15);
        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        eptr -= length;
        }
      RRETURN(MATCH_NOMATCH);
      }
    /* Control never gets here */

    /* Match a bit-mapped character class, possibly repeatedly. This op code is
    used when all the characters in the class have values in the range 0-255,
    and either the matching is caseful, or the characters are in the range
    0-127 when UTF-8 processing is enabled. The only difference between
    OP_CLASS and OP_NCLASS occurs when a data character outside the range is
    encountered.

    First, look past the end of the item to see if there is repeat information
    following. Then obey similar code to character type repeats - written out
    again for speed. */

    case OP_NCLASS:
    case OP_CLASS:
      {
      /* The data variable is saved across frames, so the byte map needs to
      be stored there. */
#define BYTE_MAP ((pcre_uint8 *)data)
      data = ecode + 1;                /* Save for matching */
      ecode += 1 + (32 / sizeof(pcre_uchar)); /* Advance past the item */

      switch (*ecode)
        {
        case OP_CRSTAR:
        case OP_CRMINSTAR:
        case OP_CRPLUS:
        case OP_CRMINPLUS:
        case OP_CRQUERY:
        case OP_CRMINQUERY:
        c = *ecode++ - OP_CRSTAR;
        minimize = (c & 1) != 0;
        min = rep_min[c];                 /* Pick up values from tables; */
        max = rep_max[c];                 /* zero for max => infinity */
        if (max == 0) max = INT_MAX;
        break;

        case OP_CRRANGE:
        case OP_CRMINRANGE:
        minimize = (*ecode == OP_CRMINRANGE);
        min = GET2(ecode, 1);
        max = GET2(ecode, 1 + IMM2_SIZE);
        if (max == 0) max = INT_MAX;
        ecode += 1 + 2 * IMM2_SIZE;
        break;

        default:               /* No repeat follows */
        min = max = 1;
        break;
        }

      /* First, ensure the minimum number of matches are present. */

#ifdef SUPPORT_UTF
      if (utf)
        {
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          if (c > 255)
            {
            if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
            }
          else
            if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
          }
        }
      else
#endif
      /* Not UTF mode */
        {
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          c = *eptr++;
#ifndef COMPILE_PCRE8
          if (c > 255)
            {
            if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
            }
          else
#endif
            if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
          }
        }

      /* If max == min we can continue with the main loop without the
      need to recurse. */

      if (min == max) continue;

      /* If minimizing, keep testing the rest of the expression and advancing
      the pointer while it matches the class. */

      if (minimize)
        {
#ifdef SUPPORT_UTF
        if (utf)
          {
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM16);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINC(c, eptr);
            if (c > 255)
              {
              if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
              }
            else
              if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
            }
          }
        else
#endif
        /* Not UTF mode */
          {
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM17);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            c = *eptr++;
#ifndef COMPILE_PCRE8
            if (c > 255)
              {
              if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
              }
            else
#endif
              if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
            }
          }
        /* Control never gets here */
        }

      /* If maximizing, find the longest possible run, then work backwards. */

      else
        {
        pp = eptr;

#ifdef SUPPORT_UTF
        if (utf)
          {
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c > 255)
              {
              if (op == OP_CLASS) break;
              }
            else
              if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
            eptr += len;
            }
          for (;;)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr-- == pp) break;        /* Stop if tried at original pos */
            BACKCHAR(eptr);
            }
          }
        else
#endif
          /* Not UTF mode */
          {
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            c = *eptr;
#ifndef COMPILE_PCRE8
            if (c > 255)
              {
              if (op == OP_CLASS) break;
              }
            else
#endif
              if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
            eptr++;
            }
          while (eptr >= pp)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM19);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            eptr--;
            }
          }

        RRETURN(MATCH_NOMATCH);
        }
#undef BYTE_MAP
      }
    /* Control never gets here */


    /* Match an extended character class. This opcode is encountered only
    when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8
    mode, because Unicode properties are supported in non-UTF-8 mode. */

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
    case OP_XCLASS:
      {
      data = ecode + 1 + LINK_SIZE;                /* Save for matching */
      ecode += GET(ecode, 1);                      /* Advance past the item */

      switch (*ecode)
        {
        case OP_CRSTAR:
        case OP_CRMINSTAR:
        case OP_CRPLUS:
        case OP_CRMINPLUS:
        case OP_CRQUERY:
        case OP_CRMINQUERY:
        c = *ecode++ - OP_CRSTAR;
        minimize = (c & 1) != 0;
        min = rep_min[c];                 /* Pick up values from tables; */
        max = rep_max[c];                 /* zero for max => infinity */
        if (max == 0) max = INT_MAX;
        break;

        case OP_CRRANGE:
        case OP_CRMINRANGE:
        minimize = (*ecode == OP_CRMINRANGE);
        min = GET2(ecode, 1);
        max = GET2(ecode, 1 + IMM2_SIZE);
        if (max == 0) max = INT_MAX;
        ecode += 1 + 2 * IMM2_SIZE;
        break;

        default:               /* No repeat follows */
        min = max = 1;
        break;
        }

      /* First, ensure the minimum number of matches are present. */

      for (i = 1; i <= min; i++)
        {
        if (eptr >= md->end_subject)
          {
          SCHECK_PARTIAL();
          RRETURN(MATCH_NOMATCH);
          }
        GETCHARINCTEST(c, eptr);
        if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH);
        }

      /* If max == min we can continue with the main loop without the
      need to recurse. */

      if (min == max) continue;

      /* If minimizing, keep testing the rest of the expression and advancing
      the pointer while it matches the class. */

      if (minimize)
        {
        for (fi = min;; fi++)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM20);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (fi >= max) RRETURN(MATCH_NOMATCH);
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINCTEST(c, eptr);
          if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH);
          }
        /* Control never gets here */
        }

      /* If maximizing, find the longest possible run, then work backwards. */

      else
        {
        pp = eptr;
        for (i = min; i < max; i++)
          {
          int len = 1;
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            break;
            }
#ifdef SUPPORT_UTF
          GETCHARLENTEST(c, eptr, len);
#else
          c = *eptr;
#endif
          if (!PRIV(xclass)(c, data, utf)) break;
          eptr += len;
          }
        for(;;)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */
#ifdef SUPPORT_UTF
          if (utf) BACKCHAR(eptr);
#endif
          }
        RRETURN(MATCH_NOMATCH);
        }

      /* Control never gets here */
      }
#endif    /* End of XCLASS */

    /* Match a single character, casefully */

    case OP_CHAR:
#ifdef SUPPORT_UTF
    if (utf)
      {
      length = 1;
      ecode++;
      GETCHARLEN(fc, ecode, length);
      if (length > md->end_subject - eptr)
        {
        CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
        RRETURN(MATCH_NOMATCH);
        }
      while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);
      }
    else
#endif
    /* Not UTF mode */
      {
      if (md->end_subject - eptr < 1)
        {
        SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
        RRETURN(MATCH_NOMATCH);
        }
      if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
      ecode += 2;
      }
    break;

    /* Match a single character, caselessly. If we are at the end of the
    subject, give up immediately. */

    case OP_CHARI:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }

#ifdef SUPPORT_UTF
    if (utf)
      {
      length = 1;
      ecode++;
      GETCHARLEN(fc, ecode, length);

      /* If the pattern character's value is < 128, we have only one byte, and
      we know that its other case must also be one byte long, so we can use the
      fast lookup table. We know that there is at least one byte left in the
      subject. */

      if (fc < 128)
        {
        if (md->lcc[fc]
            != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH);
        ecode++;
        eptr++;
        }

      /* Otherwise we must pick up the subject character. Note that we cannot
      use the value of "length" to check for sufficient bytes left, because the
      other case of the character may have more or fewer bytes.  */

      else
        {
        unsigned int dc;
        GETCHARINC(dc, eptr);
        ecode += length;

        /* If we have Unicode property support, we can use it to test the other
        case of the character, if there is one. */

        if (fc != dc)
          {
#ifdef SUPPORT_UCP
          if (dc != UCD_OTHERCASE(fc))
#endif
            RRETURN(MATCH_NOMATCH);
          }
        }
      }
    else
#endif   /* SUPPORT_UTF */

    /* Not UTF mode */
      {
      if (TABLE_GET(ecode[1], md->lcc, ecode[1])
          != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH);
      eptr++;
      ecode += 2;
      }
    break;

    /* Match a single character repeatedly. */

    case OP_EXACT:
    case OP_EXACTI:
    min = max = GET2(ecode, 1);
    ecode += 1 + IMM2_SIZE;
    goto REPEATCHAR;

    case OP_POSUPTO:
    case OP_POSUPTOI:
    possessive = TRUE;
    /* Fall through */

    case OP_UPTO:
    case OP_UPTOI:
    case OP_MINUPTO:
    case OP_MINUPTOI:
    min = 0;
    max = GET2(ecode, 1);
    minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI;
    ecode += 1 + IMM2_SIZE;
    goto REPEATCHAR;

    case OP_POSSTAR:
    case OP_POSSTARI:
    possessive = TRUE;
    min = 0;
    max = INT_MAX;
    ecode++;
    goto REPEATCHAR;

    case OP_POSPLUS:
    case OP_POSPLUSI:
    possessive = TRUE;
    min = 1;
    max = INT_MAX;
    ecode++;
    goto REPEATCHAR;

    case OP_POSQUERY:
    case OP_POSQUERYI:
    possessive = TRUE;
    min = 0;
    max = 1;
    ecode++;
    goto REPEATCHAR;

    case OP_STAR:
    case OP_STARI:
    case OP_MINSTAR:
    case OP_MINSTARI:
    case OP_PLUS:
    case OP_PLUSI:
    case OP_MINPLUS:
    case OP_MINPLUSI:
    case OP_QUERY:
    case OP_QUERYI:
    case OP_MINQUERY:
    case OP_MINQUERYI:
    c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI);
    minimize = (c & 1) != 0;
    min = rep_min[c];                 /* Pick up values from tables; */
    max = rep_max[c];                 /* zero for max => infinity */
    if (max == 0) max = INT_MAX;

    /* Common code for all repeated single-character matches. */

    REPEATCHAR:
#ifdef SUPPORT_UTF
    if (utf)
      {
      length = 1;
      charptr = ecode;
      GETCHARLEN(fc, ecode, length);
      ecode += length;

      /* Handle multibyte character matching specially here. There is
      support for caseless matching if UCP support is present. */

      if (length > 1)
        {
#ifdef SUPPORT_UCP
        unsigned int othercase;
        if (op >= OP_STARI &&     /* Caseless */
            (othercase = UCD_OTHERCASE(fc)) != fc)
          oclength = PRIV(ord2utf)(othercase, occhars);
        else oclength = 0;
#endif  /* SUPPORT_UCP */

        for (i = 1; i <= min; i++)
          {
          if (eptr <= md->end_subject - length &&
            memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
#ifdef SUPPORT_UCP
          else if (oclength > 0 &&
                   eptr <= md->end_subject - oclength &&
                   memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
#endif  /* SUPPORT_UCP */
          else
            {
            CHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          }

        if (min == max) continue;

        if (minimize)
          {
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM22);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr <= md->end_subject - length &&
              memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
#ifdef SUPPORT_UCP
            else if (oclength > 0 &&
                     eptr <= md->end_subject - oclength &&
                     memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
#endif  /* SUPPORT_UCP */
            else
              {
              CHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            }
          /* Control never gets here */
          }

        else  /* Maximize */
          {
          pp = eptr;
          for (i = min; i < max; i++)
            {
            if (eptr <= md->end_subject - length &&
                memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
#ifdef SUPPORT_UCP
            else if (oclength > 0 &&
                     eptr <= md->end_subject - oclength &&
                     memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
#endif  /* SUPPORT_UCP */
            else
              {
              CHECK_PARTIAL();
              break;
              }
            }

          if (possessive) continue;

          for(;;)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr == pp) { RRETURN(MATCH_NOMATCH); }
#ifdef SUPPORT_UCP
            eptr--;
            BACKCHAR(eptr);
#else   /* without SUPPORT_UCP */
            eptr -= length;
#endif  /* SUPPORT_UCP */
            }
          }
        /* Control never gets here */
        }

      /* If the length of a UTF-8 character is 1, we fall through here, and
      obey the code as for non-UTF-8 characters below, though in this case the
      value of fc will always be < 128. */
      }
    else
#endif  /* SUPPORT_UTF */
      /* When not in UTF-8 mode, load a single-byte character. */
      fc = *ecode++;

    /* The value of fc at this point is always one character, though we may
    or may not be in UTF mode. The code is duplicated for the caseless and
    caseful cases, for speed, since matching characters is likely to be quite
    common. First, ensure the minimum number of matches are present. If min =
    max, continue at the same level without recursing. Otherwise, if
    minimizing, keep trying the rest of the expression and advancing one
    matching character if failing, up to the maximum. Alternatively, if
    maximizing, find the maximum number of characters and work backwards. */

    DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max,
      max, (char *)eptr));

    if (op >= OP_STARI)  /* Caseless */
      {
#ifdef COMPILE_PCRE8
      /* fc must be < 128 if UTF is enabled. */
      foc = md->fcc[fc];
#else
#ifdef SUPPORT_UTF
#ifdef SUPPORT_UCP
      if (utf && fc > 127)
        foc = UCD_OTHERCASE(fc);
#else
      if (utf && fc > 127)
        foc = fc;
#endif /* SUPPORT_UCP */
      else
#endif /* SUPPORT_UTF */
        foc = TABLE_GET(fc, md->fcc, fc);
#endif /* COMPILE_PCRE8 */

      for (i = 1; i <= min; i++)
        {
        if (eptr >= md->end_subject)
          {
          SCHECK_PARTIAL();
          RRETURN(MATCH_NOMATCH);
          }
        if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH);
        eptr++;
        }
      if (min == max) continue;
      if (minimize)
        {
        for (fi = min;; fi++)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM24);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (fi >= max) RRETURN(MATCH_NOMATCH);
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        /* Control never gets here */
        }
      else  /* Maximize */
        {
        pp = eptr;
        for (i = min; i < max; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            break;
            }
          if (fc != *eptr && foc != *eptr) break;
          eptr++;
          }

        if (possessive) continue;

        while (eptr >= pp)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);
          eptr--;
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          }
        RRETURN(MATCH_NOMATCH);
        }
      /* Control never gets here */
      }

    /* Caseful comparisons (includes all multi-byte characters) */

    else
      {
      for (i = 1; i <= min; i++)
        {
        if (eptr >= md->end_subject)
          {
          SCHECK_PARTIAL();
          RRETURN(MATCH_NOMATCH);
          }
        if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
        }

      if (min == max) continue;

      if (minimize)
        {
        for (fi = min;; fi++)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM26);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (fi >= max) RRETURN(MATCH_NOMATCH);
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
          }
        /* Control never gets here */
        }
      else  /* Maximize */
        {
        pp = eptr;
        for (i = min; i < max; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            break;
            }
          if (fc != *eptr) break;
          eptr++;
          }
        if (possessive) continue;

        while (eptr >= pp)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);
          eptr--;
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          }
        RRETURN(MATCH_NOMATCH);
        }
      }
    /* Control never gets here */

    /* Match a negated single one-byte character. The character we are
    checking can be multibyte. */

    case OP_NOT:
    case OP_NOTI:
    if (eptr >= md->end_subject)
      {
      SCHECK_PARTIAL();
      RRETURN(MATCH_NOMATCH);
      }
#ifdef SUPPORT_UTF
    if (utf)
      {
      register unsigned int ch, och;

      ecode++;
      GETCHARINC(ch, ecode);
      GETCHARINC(c, eptr);

      if (op == OP_NOT)
        {
        if (ch == c) RRETURN(MATCH_NOMATCH);
        }
      else
        {
#ifdef SUPPORT_UCP
        if (ch > 127)
          och = UCD_OTHERCASE(ch);
#else
        if (ch > 127)
          och = ch;
#endif /* SUPPORT_UCP */
        else
          och = TABLE_GET(ch, md->fcc, ch);
        if (ch == c || och == c) RRETURN(MATCH_NOMATCH);
        }
      }
    else
#endif
      {
      register unsigned int ch = ecode[1];
      c = *eptr++;
      if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c))
        RRETURN(MATCH_NOMATCH);
      ecode += 2;
      }
    break;

    /* Match a negated single one-byte character repeatedly. This is almost a
    repeat of the code for a repeated single character, but I haven't found a
    nice way of commoning these up that doesn't require a test of the
    positive/negative option for each character match. Maybe that wouldn't add
    very much to the time taken, but character matching *is* what this is all
    about... */

    case OP_NOTEXACT:
    case OP_NOTEXACTI:
    min = max = GET2(ecode, 1);
    ecode += 1 + IMM2_SIZE;
    goto REPEATNOTCHAR;

    case OP_NOTUPTO:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTO:
    case OP_NOTMINUPTOI:
    min = 0;
    max = GET2(ecode, 1);
    minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI;
    ecode += 1 + IMM2_SIZE;
    goto REPEATNOTCHAR;

    case OP_NOTPOSSTAR:
    case OP_NOTPOSSTARI:
    possessive = TRUE;
    min = 0;
    max = INT_MAX;
    ecode++;
    goto REPEATNOTCHAR;

    case OP_NOTPOSPLUS:
    case OP_NOTPOSPLUSI:
    possessive = TRUE;
    min = 1;
    max = INT_MAX;
    ecode++;
    goto REPEATNOTCHAR;

    case OP_NOTPOSQUERY:
    case OP_NOTPOSQUERYI:
    possessive = TRUE;
    min = 0;
    max = 1;
    ecode++;
    goto REPEATNOTCHAR;

    case OP_NOTPOSUPTO:
    case OP_NOTPOSUPTOI:
    possessive = TRUE;
    min = 0;
    max = GET2(ecode, 1);
    ecode += 1 + IMM2_SIZE;
    goto REPEATNOTCHAR;

    case OP_NOTSTAR:
    case OP_NOTSTARI:
    case OP_NOTMINSTAR:
    case OP_NOTMINSTARI:
    case OP_NOTPLUS:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUS:
    case OP_NOTMINPLUSI:
    case OP_NOTQUERY:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERY:
    case OP_NOTMINQUERYI:
    c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR);
    minimize = (c & 1) != 0;
    min = rep_min[c];                 /* Pick up values from tables; */
    max = rep_max[c];                 /* zero for max => infinity */
    if (max == 0) max = INT_MAX;

    /* Common code for all repeated single-byte matches. */

    REPEATNOTCHAR:
    GETCHARINCTEST(fc, ecode);

    /* The code is duplicated for the caseless and caseful cases, for speed,
    since matching characters is likely to be quite common. First, ensure the
    minimum number of matches are present. If min = max, continue at the same
    level without recursing. Otherwise, if minimizing, keep trying the rest of
    the expression and advancing one matching character if failing, up to the
    maximum. Alternatively, if maximizing, find the maximum number of
    characters and work backwards. */

    DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max,
      max, (char *)eptr));

    if (op >= OP_NOTSTARI)     /* Caseless */
      {
#ifdef SUPPORT_UTF
#ifdef SUPPORT_UCP
      if (utf && fc > 127)
        foc = UCD_OTHERCASE(fc);
#else
      if (utf && fc > 127)
        foc = fc;
#endif /* SUPPORT_UCP */
      else
#endif /* SUPPORT_UTF */
        foc = TABLE_GET(fc, md->fcc, fc);

#ifdef SUPPORT_UTF
      if (utf)
        {
        register unsigned int d;
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(d, eptr);
          if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
          }
        }
      else
#endif
      /* Not UTF mode */
        {
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        }

      if (min == max) continue;

      if (minimize)
        {
#ifdef SUPPORT_UTF
        if (utf)
          {
          register unsigned int d;
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM28);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINC(d, eptr);
            if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
            }
          }
        else
#endif
        /* Not UTF mode */
          {
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM29);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH);
            eptr++;
            }
          }
        /* Control never gets here */
        }

      /* Maximize case */

      else
        {
        pp = eptr;

#ifdef SUPPORT_UTF
        if (utf)
          {
          register unsigned int d;
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(d, eptr, len);
            if (fc == d || (unsigned int)foc == d) break;
            eptr += len;
            }
          if (possessive) continue;
          for(;;)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr-- == pp) break;        /* Stop if tried at original pos */
            BACKCHAR(eptr);
            }
          }
        else
#endif
        /* Not UTF mode */
          {
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (fc == *eptr || foc == *eptr) break;
            eptr++;
            }
          if (possessive) continue;
          while (eptr >= pp)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            eptr--;
            }
          }

        RRETURN(MATCH_NOMATCH);
        }
      /* Control never gets here */
      }

    /* Caseful comparisons */

    else
      {
#ifdef SUPPORT_UTF
      if (utf)
        {
        register unsigned int d;
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(d, eptr);
          if (fc == d) RRETURN(MATCH_NOMATCH);
          }
        }
      else
#endif
      /* Not UTF mode */
        {
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
          }
        }

      if (min == max) continue;

      if (minimize)
        {
#ifdef SUPPORT_UTF
        if (utf)
          {
          register unsigned int d;
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM32);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINC(d, eptr);
            if (fc == d) RRETURN(MATCH_NOMATCH);
            }
          }
        else
#endif
        /* Not UTF mode */
          {
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM33);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
            }
          }
        /* Control never gets here */
        }

      /* Maximize case */

      else
        {
        pp = eptr;

#ifdef SUPPORT_UTF
        if (utf)
          {
          register unsigned int d;
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(d, eptr, len);
            if (fc == d) break;
            eptr += len;
            }
          if (possessive) continue;
          for(;;)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr-- == pp) break;        /* Stop if tried at original pos */
            BACKCHAR(eptr);
            }
          }
        else
#endif
        /* Not UTF mode */
          {
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (fc == *eptr) break;
            eptr++;
            }
          if (possessive) continue;
          while (eptr >= pp)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            eptr--;
            }
          }

        RRETURN(MATCH_NOMATCH);
        }
      }
    /* Control never gets here */

    /* Match a single character type repeatedly; several different opcodes
    share code. This is very similar to the code for single characters, but we
    repeat it in the interests of efficiency. */

    case OP_TYPEEXACT:
    min = max = GET2(ecode, 1);
    minimize = TRUE;
    ecode += 1 + IMM2_SIZE;
    goto REPEATTYPE;

    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    min = 0;
    max = GET2(ecode, 1);
    minimize = *ecode == OP_TYPEMINUPTO;
    ecode += 1 + IMM2_SIZE;
    goto REPEATTYPE;

    case OP_TYPEPOSSTAR:
    possessive = TRUE;
    min = 0;
    max = INT_MAX;
    ecode++;
    goto REPEATTYPE;

    case OP_TYPEPOSPLUS:
    possessive = TRUE;
    min = 1;
    max = INT_MAX;
    ecode++;
    goto REPEATTYPE;

    case OP_TYPEPOSQUERY:
    possessive = TRUE;
    min = 0;
    max = 1;
    ecode++;
    goto REPEATTYPE;

    case OP_TYPEPOSUPTO:
    possessive = TRUE;
    min = 0;
    max = GET2(ecode, 1);
    ecode += 1 + IMM2_SIZE;
    goto REPEATTYPE;

    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    c = *ecode++ - OP_TYPESTAR;
    minimize = (c & 1) != 0;
    min = rep_min[c];                 /* Pick up values from tables; */
    max = rep_max[c];                 /* zero for max => infinity */
    if (max == 0) max = INT_MAX;

    /* Common code for all repeated single character type matches. Note that
    in UTF-8 mode, '.' matches a character of any length, but for the other
    character types, the valid characters are all one-byte long. */

    REPEATTYPE:
    ctype = *ecode++;      /* Code for the character type */

#ifdef SUPPORT_UCP
    if (ctype == OP_PROP || ctype == OP_NOTPROP)
      {
      prop_fail_result = ctype == OP_NOTPROP;
      prop_type = *ecode++;
      prop_value = *ecode++;
      }
    else prop_type = -1;
#endif

    /* First, ensure the minimum number of matches are present. Use inline
    code for maximizing the speed, and do the type test once at the start
    (i.e. keep it out of the loop). Separate the UTF-8 code completely as that
    is tidier. Also separate the UCP code, which can be the same for both UTF-8
    and single-bytes. */

    if (min > 0)
      {
#ifdef SUPPORT_UCP
      if (prop_type >= 0)
        {
        switch(prop_type)
          {
          case PT_ANY:
          if (prop_fail_result) RRETURN(MATCH_NOMATCH);
          for (i = 1; i <= min; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            }
          break;

          case PT_LAMP:
          for (i = 1; i <= min; i++)
            {
            int chartype;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            chartype = UCD_CHARTYPE(c);
            if ((chartype == ucp_Lu ||
                 chartype == ucp_Ll ||
                 chartype == ucp_Lt) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_GC:
          for (i = 1; i <= min; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_PC:
          for (i = 1; i <= min; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_SC:
          for (i = 1; i <= min; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_ALNUM:
          for (i = 1; i <= min; i++)
            {
            int category;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            category = UCD_CATEGORY(c);
            if ((category == ucp_L || category == ucp_N) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_SPACE:    /* Perl space */
          for (i = 1; i <= min; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                 c == CHAR_FF || c == CHAR_CR)
                   == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_PXSPACE:  /* POSIX space */
          for (i = 1; i <= min; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
                   == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          case PT_WORD:
          for (i = 1; i <= min; i++)
            {
            int category;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            category = UCD_CATEGORY(c);
            if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE)
                   == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          break;

          /* This should not occur */

          default:
          RRETURN(PCRE_ERROR_INTERNAL);
          }
        }

      /* Match extended Unicode sequences. We will get here only if the
      support is in the binary; otherwise a compile-time error occurs. */

      else if (ctype == OP_EXTUNI)
        {
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINCTEST(c, eptr);
          if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH);
          while (eptr < md->end_subject)
            {
            int len = 1;
            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
            if (UCD_CATEGORY(c) != ucp_M) break;
            eptr += len;
            }
          CHECK_PARTIAL();
          }
        }

      else
#endif     /* SUPPORT_UCP */

/* Handle all other cases when the coding is UTF-8 */

#ifdef SUPPORT_UTF
      if (utf) switch(ctype)
        {
        case OP_ANY:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
          if (md->partial != 0 &&
              eptr + 1 >= md->end_subject &&
              NLBLOCK->nltype == NLTYPE_FIXED &&
              NLBLOCK->nllen == 2 &&
              *eptr == NLBLOCK->nl[0])
            {
            md->hitend = TRUE;
            if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
            }
          eptr++;
          ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
          }
        break;

        case OP_ALLANY:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          eptr++;
          ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
          }
        break;

        case OP_ANYBYTE:
        if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH);
        eptr += min;
        break;

        case OP_ANYNL:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          switch(c)
            {
            default: RRETURN(MATCH_NOMATCH);

            case 0x000d:
            if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
            break;

            case 0x000a:
            break;

            case 0x000b:
            case 0x000c:
            case 0x0085:
            case 0x2028:
            case 0x2029:
            if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
            break;
            }
          }
        break;

        case OP_NOT_HSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          switch(c)
            {
            default: break;
            case 0x09:      /* HT */
            case 0x20:      /* SPACE */
            case 0xa0:      /* NBSP */
            case 0x1680:    /* OGHAM SPACE MARK */
            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
            case 0x2000:    /* EN QUAD */
            case 0x2001:    /* EM QUAD */
            case 0x2002:    /* EN SPACE */
            case 0x2003:    /* EM SPACE */
            case 0x2004:    /* THREE-PER-EM SPACE */
            case 0x2005:    /* FOUR-PER-EM SPACE */
            case 0x2006:    /* SIX-PER-EM SPACE */
            case 0x2007:    /* FIGURE SPACE */
            case 0x2008:    /* PUNCTUATION SPACE */
            case 0x2009:    /* THIN SPACE */
            case 0x200A:    /* HAIR SPACE */
            case 0x202f:    /* NARROW NO-BREAK SPACE */
            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
            case 0x3000:    /* IDEOGRAPHIC SPACE */
            RRETURN(MATCH_NOMATCH);
            }
          }
        break;

        case OP_HSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          switch(c)
            {
            default: RRETURN(MATCH_NOMATCH);
            case 0x09:      /* HT */
            case 0x20:      /* SPACE */
            case 0xa0:      /* NBSP */
            case 0x1680:    /* OGHAM SPACE MARK */
            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
            case 0x2000:    /* EN QUAD */
            case 0x2001:    /* EM QUAD */
            case 0x2002:    /* EN SPACE */
            case 0x2003:    /* EM SPACE */
            case 0x2004:    /* THREE-PER-EM SPACE */
            case 0x2005:    /* FOUR-PER-EM SPACE */
            case 0x2006:    /* SIX-PER-EM SPACE */
            case 0x2007:    /* FIGURE SPACE */
            case 0x2008:    /* PUNCTUATION SPACE */
            case 0x2009:    /* THIN SPACE */
            case 0x200A:    /* HAIR SPACE */
            case 0x202f:    /* NARROW NO-BREAK SPACE */
            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
            case 0x3000:    /* IDEOGRAPHIC SPACE */
            break;
            }
          }
        break;

        case OP_NOT_VSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          switch(c)
            {
            default: break;
            case 0x0a:      /* LF */
            case 0x0b:      /* VT */
            case 0x0c:      /* FF */
            case 0x0d:      /* CR */
            case 0x85:      /* NEL */
            case 0x2028:    /* LINE SEPARATOR */
            case 0x2029:    /* PARAGRAPH SEPARATOR */
            RRETURN(MATCH_NOMATCH);
            }
          }
        break;

        case OP_VSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          switch(c)
            {
            default: RRETURN(MATCH_NOMATCH);
            case 0x0a:      /* LF */
            case 0x0b:      /* VT */
            case 0x0c:      /* FF */
            case 0x0d:      /* CR */
            case 0x85:      /* NEL */
            case 0x2028:    /* LINE SEPARATOR */
            case 0x2029:    /* PARAGRAPH SEPARATOR */
            break;
            }
          }
        break;

        case OP_NOT_DIGIT:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINC(c, eptr);
          if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
            RRETURN(MATCH_NOMATCH);
          }
        break;

        case OP_DIGIT:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_digit) == 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          /* No need to skip more bytes - we know it's a 1-byte character */
          }
        break;

        case OP_NOT_WHITESPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
          }
        break;

        case OP_WHITESPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_space) == 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          /* No need to skip more bytes - we know it's a 1-byte character */
          }
        break;

        case OP_NOT_WORDCHAR:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
          }
        break;

        case OP_WORDCHAR:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_word) == 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          /* No need to skip more bytes - we know it's a 1-byte character */
          }
        break;

        default:
        RRETURN(PCRE_ERROR_INTERNAL);
        }  /* End switch(ctype) */

      else
#endif     /* SUPPORT_UTF */

      /* Code for the non-UTF-8 case for minimum matching of operators other
      than OP_PROP and OP_NOTPROP. */

      switch(ctype)
        {
        case OP_ANY:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
          if (md->partial != 0 &&
              eptr + 1 >= md->end_subject &&
              NLBLOCK->nltype == NLTYPE_FIXED &&
              NLBLOCK->nllen == 2 &&
              *eptr == NLBLOCK->nl[0])
            {
            md->hitend = TRUE;
            if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
            }
          eptr++;
          }
        break;

        case OP_ALLANY:
        if (eptr > md->end_subject - min)
          {
          SCHECK_PARTIAL();
          RRETURN(MATCH_NOMATCH);
          }
        eptr += min;
        break;

        case OP_ANYBYTE:
        if (eptr > md->end_subject - min)
          {
          SCHECK_PARTIAL();
          RRETURN(MATCH_NOMATCH);
          }
        eptr += min;
        break;

        case OP_ANYNL:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          switch(*eptr++)
            {
            default: RRETURN(MATCH_NOMATCH);

            case 0x000d:
            if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
            break;

            case 0x000a:
            break;

            case 0x000b:
            case 0x000c:
            case 0x0085:
#ifdef COMPILE_PCRE16
            case 0x2028:
            case 0x2029:
#endif
            if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
            break;
            }
          }
        break;

        case OP_NOT_HSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          switch(*eptr++)
            {
            default: break;
            case 0x09:      /* HT */
            case 0x20:      /* SPACE */
            case 0xa0:      /* NBSP */
#ifdef COMPILE_PCRE16
            case 0x1680:    /* OGHAM SPACE MARK */
            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
            case 0x2000:    /* EN QUAD */
            case 0x2001:    /* EM QUAD */
            case 0x2002:    /* EN SPACE */
            case 0x2003:    /* EM SPACE */
            case 0x2004:    /* THREE-PER-EM SPACE */
            case 0x2005:    /* FOUR-PER-EM SPACE */
            case 0x2006:    /* SIX-PER-EM SPACE */
            case 0x2007:    /* FIGURE SPACE */
            case 0x2008:    /* PUNCTUATION SPACE */
            case 0x2009:    /* THIN SPACE */
            case 0x200A:    /* HAIR SPACE */
            case 0x202f:    /* NARROW NO-BREAK SPACE */
            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
            case 0x3000:    /* IDEOGRAPHIC SPACE */
#endif
            RRETURN(MATCH_NOMATCH);
            }
          }
        break;

        case OP_HSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          switch(*eptr++)
            {
            default: RRETURN(MATCH_NOMATCH);
            case 0x09:      /* HT */
            case 0x20:      /* SPACE */
            case 0xa0:      /* NBSP */
#ifdef COMPILE_PCRE16
            case 0x1680:    /* OGHAM SPACE MARK */
            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
            case 0x2000:    /* EN QUAD */
            case 0x2001:    /* EM QUAD */
            case 0x2002:    /* EN SPACE */
            case 0x2003:    /* EM SPACE */
            case 0x2004:    /* THREE-PER-EM SPACE */
            case 0x2005:    /* FOUR-PER-EM SPACE */
            case 0x2006:    /* SIX-PER-EM SPACE */
            case 0x2007:    /* FIGURE SPACE */
            case 0x2008:    /* PUNCTUATION SPACE */
            case 0x2009:    /* THIN SPACE */
            case 0x200A:    /* HAIR SPACE */
            case 0x202f:    /* NARROW NO-BREAK SPACE */
            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
            case 0x3000:    /* IDEOGRAPHIC SPACE */
#endif
            break;
            }
          }
        break;

        case OP_NOT_VSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          switch(*eptr++)
            {
            default: break;
            case 0x0a:      /* LF */
            case 0x0b:      /* VT */
            case 0x0c:      /* FF */
            case 0x0d:      /* CR */
            case 0x85:      /* NEL */
#ifdef COMPILE_PCRE16
            case 0x2028:    /* LINE SEPARATOR */
            case 0x2029:    /* PARAGRAPH SEPARATOR */
#endif
            RRETURN(MATCH_NOMATCH);
            }
          }
        break;

        case OP_VSPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          switch(*eptr++)
            {
            default: RRETURN(MATCH_NOMATCH);
            case 0x0a:      /* LF */
            case 0x0b:      /* VT */
            case 0x0c:      /* FF */
            case 0x0d:      /* CR */
            case 0x85:      /* NEL */
#ifdef COMPILE_PCRE16
            case 0x2028:    /* LINE SEPARATOR */
            case 0x2029:    /* PARAGRAPH SEPARATOR */
#endif
            break;
            }
          }
        break;

        case OP_NOT_DIGIT:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        break;

        case OP_DIGIT:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        break;

        case OP_NOT_WHITESPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        break;

        case OP_WHITESPACE:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        break;

        case OP_NOT_WORDCHAR:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        break;

        case OP_WORDCHAR:
        for (i = 1; i <= min; i++)
          {
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0)
            RRETURN(MATCH_NOMATCH);
          eptr++;
          }
        break;

        default:
        RRETURN(PCRE_ERROR_INTERNAL);
        }
      }

    /* If min = max, continue at the same level without recursing */

    if (min == max) continue;

    /* If minimizing, we have to test the rest of the pattern before each
    subsequent match. Again, separate the UTF-8 case for speed, and also
    separate the UCP cases. */

    if (minimize)
      {
#ifdef SUPPORT_UCP
      if (prop_type >= 0)
        {
        switch(prop_type)
          {
          case PT_ANY:
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM36);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if (prop_fail_result) RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_LAMP:
          for (fi = min;; fi++)
            {
            int chartype;
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM37);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            chartype = UCD_CHARTYPE(c);
            if ((chartype == ucp_Lu ||
                 chartype == ucp_Ll ||
                 chartype == ucp_Lt) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_GC:
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM38);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_PC:
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM39);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_SC:
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM40);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_ALNUM:
          for (fi = min;; fi++)
            {
            int category;
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM59);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            category = UCD_CATEGORY(c);
            if ((category == ucp_L || category == ucp_N) == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_SPACE:    /* Perl space */
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM60);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                 c == CHAR_FF || c == CHAR_CR)
                   == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_PXSPACE:  /* POSIX space */
          for (fi = min;; fi++)
            {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM61);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
                   == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          case PT_WORD:
          for (fi = min;; fi++)
            {
            int category;
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM62);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (fi >= max) RRETURN(MATCH_NOMATCH);
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              RRETURN(MATCH_NOMATCH);
              }
            GETCHARINCTEST(c, eptr);
            category = UCD_CATEGORY(c);
            if ((category == ucp_L ||
                 category == ucp_N ||
                 c == CHAR_UNDERSCORE)
                   == prop_fail_result)
              RRETURN(MATCH_NOMATCH);
            }
          /* Control never gets here */

          /* This should never occur */

          default:
          RRETURN(PCRE_ERROR_INTERNAL);
          }
        }

      /* Match extended Unicode sequences. We will get here only if the
      support is in the binary; otherwise a compile-time error occurs. */

      else if (ctype == OP_EXTUNI)
        {
        for (fi = min;; fi++)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM41);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (fi >= max) RRETURN(MATCH_NOMATCH);
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          GETCHARINCTEST(c, eptr);
          if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH);
          while (eptr < md->end_subject)
            {
            int len = 1;
            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
            if (UCD_CATEGORY(c) != ucp_M) break;
            eptr += len;
            }
          CHECK_PARTIAL();
          }
        }
      else
#endif     /* SUPPORT_UCP */

#ifdef SUPPORT_UTF
      if (utf)
        {
        for (fi = min;; fi++)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM42);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (fi >= max) RRETURN(MATCH_NOMATCH);
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (ctype == OP_ANY && IS_NEWLINE(eptr))
            RRETURN(MATCH_NOMATCH);
          GETCHARINC(c, eptr);
          switch(ctype)
            {
            case OP_ANY:               /* This is the non-NL case */
            if (md->partial != 0 &&    /* Take care with CRLF partial */
                eptr >= md->end_subject &&
                NLBLOCK->nltype == NLTYPE_FIXED &&
                NLBLOCK->nllen == 2 &&
                c == NLBLOCK->nl[0])
              {
              md->hitend = TRUE;
              if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
              }
            break;

            case OP_ALLANY:
            case OP_ANYBYTE:
            break;

            case OP_ANYNL:
            switch(c)
              {
              default: RRETURN(MATCH_NOMATCH);
              case 0x000d:
              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
              break;
              case 0x000a:
              break;

              case 0x000b:
              case 0x000c:
              case 0x0085:
              case 0x2028:
              case 0x2029:
              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
              break;
              }
            break;

            case OP_NOT_HSPACE:
            switch(c)
              {
              default: break;
              case 0x09:      /* HT */
              case 0x20:      /* SPACE */
              case 0xa0:      /* NBSP */
              case 0x1680:    /* OGHAM SPACE MARK */
              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
              case 0x2000:    /* EN QUAD */
              case 0x2001:    /* EM QUAD */
              case 0x2002:    /* EN SPACE */
              case 0x2003:    /* EM SPACE */
              case 0x2004:    /* THREE-PER-EM SPACE */
              case 0x2005:    /* FOUR-PER-EM SPACE */
              case 0x2006:    /* SIX-PER-EM SPACE */
              case 0x2007:    /* FIGURE SPACE */
              case 0x2008:    /* PUNCTUATION SPACE */
              case 0x2009:    /* THIN SPACE */
              case 0x200A:    /* HAIR SPACE */
              case 0x202f:    /* NARROW NO-BREAK SPACE */
              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
              case 0x3000:    /* IDEOGRAPHIC SPACE */
              RRETURN(MATCH_NOMATCH);
              }
            break;

            case OP_HSPACE:
            switch(c)
              {
              default: RRETURN(MATCH_NOMATCH);
              case 0x09:      /* HT */
              case 0x20:      /* SPACE */
              case 0xa0:      /* NBSP */
              case 0x1680:    /* OGHAM SPACE MARK */
              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
              case 0x2000:    /* EN QUAD */
              case 0x2001:    /* EM QUAD */
              case 0x2002:    /* EN SPACE */
              case 0x2003:    /* EM SPACE */
              case 0x2004:    /* THREE-PER-EM SPACE */
              case 0x2005:    /* FOUR-PER-EM SPACE */
              case 0x2006:    /* SIX-PER-EM SPACE */
              case 0x2007:    /* FIGURE SPACE */
              case 0x2008:    /* PUNCTUATION SPACE */
              case 0x2009:    /* THIN SPACE */
              case 0x200A:    /* HAIR SPACE */
              case 0x202f:    /* NARROW NO-BREAK SPACE */
              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
              case 0x3000:    /* IDEOGRAPHIC SPACE */
              break;
              }
            break;

            case OP_NOT_VSPACE:
            switch(c)
              {
              default: break;
              case 0x0a:      /* LF */
              case 0x0b:      /* VT */
              case 0x0c:      /* FF */
              case 0x0d:      /* CR */
              case 0x85:      /* NEL */
              case 0x2028:    /* LINE SEPARATOR */
              case 0x2029:    /* PARAGRAPH SEPARATOR */
              RRETURN(MATCH_NOMATCH);
              }
            break;

            case OP_VSPACE:
            switch(c)
              {
              default: RRETURN(MATCH_NOMATCH);
              case 0x0a:      /* LF */
              case 0x0b:      /* VT */
              case 0x0c:      /* FF */
              case 0x0d:      /* CR */
              case 0x85:      /* NEL */
              case 0x2028:    /* LINE SEPARATOR */
              case 0x2029:    /* PARAGRAPH SEPARATOR */
              break;
              }
            break;

            case OP_NOT_DIGIT:
            if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
              RRETURN(MATCH_NOMATCH);
            break;

            case OP_DIGIT:
            if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
              RRETURN(MATCH_NOMATCH);
            break;

            case OP_NOT_WHITESPACE:
            if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
              RRETURN(MATCH_NOMATCH);
            break;

            case OP_WHITESPACE:
            if (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
              RRETURN(MATCH_NOMATCH);
            break;

            case OP_NOT_WORDCHAR:
            if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
              RRETURN(MATCH_NOMATCH);
            break;

            case OP_WORDCHAR:
            if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
              RRETURN(MATCH_NOMATCH);
            break;

            default:
            RRETURN(PCRE_ERROR_INTERNAL);
            }
          }
        }
      else
#endif
      /* Not UTF mode */
        {
        for (fi = min;; fi++)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM43);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (fi >= max) RRETURN(MATCH_NOMATCH);
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            RRETURN(MATCH_NOMATCH);
            }
          if (ctype == OP_ANY && IS_NEWLINE(eptr))
            RRETURN(MATCH_NOMATCH);
          c = *eptr++;
          switch(ctype)
            {
            case OP_ANY:               /* This is the non-NL case */
            if (md->partial != 0 &&    /* Take care with CRLF partial */
                eptr >= md->end_subject &&
                NLBLOCK->nltype == NLTYPE_FIXED &&
                NLBLOCK->nllen == 2 &&
                c == NLBLOCK->nl[0])
              {
              md->hitend = TRUE;
              if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
              }
            break;

            case OP_ALLANY:
            case OP_ANYBYTE:
            break;

            case OP_ANYNL:
            switch(c)
              {
              default: RRETURN(MATCH_NOMATCH);
              case 0x000d:
              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
              break;

              case 0x000a:
              break;

              case 0x000b:
              case 0x000c:
              case 0x0085:
#ifdef COMPILE_PCRE16
              case 0x2028:
              case 0x2029:
#endif
              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
              break;
              }
            break;

            case OP_NOT_HSPACE:
            switch(c)
              {
              default: break;
              case 0x09:      /* HT */
              case 0x20:      /* SPACE */
              case 0xa0:      /* NBSP */
#ifdef COMPILE_PCRE16
              case 0x1680:    /* OGHAM SPACE MARK */
              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
              case 0x2000:    /* EN QUAD */
              case 0x2001:    /* EM QUAD */
              case 0x2002:    /* EN SPACE */
              case 0x2003:    /* EM SPACE */
              case 0x2004:    /* THREE-PER-EM SPACE */
              case 0x2005:    /* FOUR-PER-EM SPACE */
              case 0x2006:    /* SIX-PER-EM SPACE */
              case 0x2007:    /* FIGURE SPACE */
              case 0x2008:    /* PUNCTUATION SPACE */
              case 0x2009:    /* THIN SPACE */
              case 0x200A:    /* HAIR SPACE */
              case 0x202f:    /* NARROW NO-BREAK SPACE */
              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
              case 0x3000:    /* IDEOGRAPHIC SPACE */
#endif
              RRETURN(MATCH_NOMATCH);
              }
            break;

            case OP_HSPACE:
            switch(c)
              {
              default: RRETURN(MATCH_NOMATCH);
              case 0x09:      /* HT */
              case 0x20:      /* SPACE */
              case 0xa0:      /* NBSP */
#ifdef COMPILE_PCRE16
              case 0x1680:    /* OGHAM SPACE MARK */
              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
              case 0x2000:    /* EN QUAD */
              case 0x2001:    /* EM QUAD */
              case 0x2002:    /* EN SPACE */
              case 0x2003:    /* EM SPACE */
              case 0x2004:    /* THREE-PER-EM SPACE */
              case 0x2005:    /* FOUR-PER-EM SPACE */
              case 0x2006:    /* SIX-PER-EM SPACE */
              case 0x2007:    /* FIGURE SPACE */
              case 0x2008:    /* PUNCTUATION SPACE */
              case 0x2009:    /* THIN SPACE */
              case 0x200A:    /* HAIR SPACE */
              case 0x202f:    /* NARROW NO-BREAK SPACE */
              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
              case 0x3000:    /* IDEOGRAPHIC SPACE */
#endif
              break;
              }
            break;

            case OP_NOT_VSPACE:
            switch(c)
              {
              default: break;
              case 0x0a:      /* LF */
              case 0x0b:      /* VT */
              case 0x0c:      /* FF */
              case 0x0d:      /* CR */
              case 0x85:      /* NEL */
#ifdef COMPILE_PCRE16
              case 0x2028:    /* LINE SEPARATOR */
              case 0x2029:    /* PARAGRAPH SEPARATOR */
#endif
              RRETURN(MATCH_NOMATCH);
              }
            break;

            case OP_VSPACE:
            switch(c)
              {
              default: RRETURN(MATCH_NOMATCH);
              case 0x0a:      /* LF */
              case 0x0b:      /* VT */
              case 0x0c:      /* FF */
              case 0x0d:      /* CR */
              case 0x85:      /* NEL */
#ifdef COMPILE_PCRE16
              case 0x2028:    /* LINE SEPARATOR */
              case 0x2029:    /* PARAGRAPH SEPARATOR */
#endif
              break;
              }
            break;

            case OP_NOT_DIGIT:
            if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
            break;

            case OP_DIGIT:
            if (!MAX_255(c) || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
            break;

            case OP_NOT_WHITESPACE:
            if (MAX_255(c) && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
            break;

            case OP_WHITESPACE:
            if (!MAX_255(c) || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
            break;

            case OP_NOT_WORDCHAR:
            if (MAX_255(c) && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);
            break;

            case OP_WORDCHAR:
            if (!MAX_255(c) || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);
            break;

            default:
            RRETURN(PCRE_ERROR_INTERNAL);
            }
          }
        }
      /* Control never gets here */
      }

    /* If maximizing, it is worth using inline code for speed, doing the type
    test once at the start (i.e. keep it out of the loop). Again, keep the
    UTF-8 and UCP stuff separate. */

    else
      {
      pp = eptr;  /* Remember where we started */

#ifdef SUPPORT_UCP
      if (prop_type >= 0)
        {
        switch(prop_type)
          {
          case PT_ANY:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            if (prop_fail_result) break;
            eptr+= len;
            }
          break;

          case PT_LAMP:
          for (i = min; i < max; i++)
            {
            int chartype;
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            chartype = UCD_CHARTYPE(c);
            if ((chartype == ucp_Lu ||
                 chartype == ucp_Ll ||
                 chartype == ucp_Lt) == prop_fail_result)
              break;
            eptr+= len;
            }
          break;

          case PT_GC:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break;
            eptr+= len;
            }
          break;

          case PT_PC:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break;
            eptr+= len;
            }
          break;

          case PT_SC:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break;
            eptr+= len;
            }
          break;

          case PT_ALNUM:
          for (i = min; i < max; i++)
            {
            int category;
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            category = UCD_CATEGORY(c);
            if ((category == ucp_L || category == ucp_N) == prop_fail_result)
              break;
            eptr+= len;
            }
          break;

          case PT_SPACE:    /* Perl space */
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                 c == CHAR_FF || c == CHAR_CR)
                 == prop_fail_result)
              break;
            eptr+= len;
            }
          break;

          case PT_PXSPACE:  /* POSIX space */
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
                 == prop_fail_result)
              break;
            eptr+= len;
            }
          break;

          case PT_WORD:
          for (i = min; i < max; i++)
            {
            int category;
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLENTEST(c, eptr, len);
            category = UCD_CATEGORY(c);
            if ((category == ucp_L || category == ucp_N ||
                 c == CHAR_UNDERSCORE) == prop_fail_result)
              break;
            eptr+= len;
            }
          break;

          default:
          RRETURN(PCRE_ERROR_INTERNAL);
          }

        /* eptr is now past the end of the maximum run */

        if (possessive) continue;
        for(;;)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */
          if (utf) BACKCHAR(eptr);
          }
        }

      /* Match extended Unicode sequences. We will get here only if the
      support is in the binary; otherwise a compile-time error occurs. */

      else if (ctype == OP_EXTUNI)
        {
        for (i = min; i < max; i++)
          {
          int len = 1;
          if (eptr >= md->end_subject)
            {
            SCHECK_PARTIAL();
            break;
            }
          if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
          if (UCD_CATEGORY(c) == ucp_M) break;
          eptr += len;
          while (eptr < md->end_subject)
            {
            len = 1;
            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
            if (UCD_CATEGORY(c) != ucp_M) break;
            eptr += len;
            }
          CHECK_PARTIAL();
          }

        /* eptr is now past the end of the maximum run */

        if (possessive) continue;

        for(;;)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */
          for (;;)                        /* Move back over one extended */
            {
            if (!utf) c = *eptr; else
              {
              BACKCHAR(eptr);
              GETCHAR(c, eptr);
              }
            if (UCD_CATEGORY(c) != ucp_M) break;
            eptr--;
            }
          }
        }

      else
#endif   /* SUPPORT_UCP */

#ifdef SUPPORT_UTF
      if (utf)
        {
        switch(ctype)
          {
          case OP_ANY:
          if (max < INT_MAX)
            {
            for (i = min; i < max; i++)
              {
              if (eptr >= md->end_subject)
                {
                SCHECK_PARTIAL();
                break;
                }
              if (IS_NEWLINE(eptr)) break;
              if (md->partial != 0 &&    /* Take care with CRLF partial */
                  eptr + 1 >= md->end_subject &&
                  NLBLOCK->nltype == NLTYPE_FIXED &&
                  NLBLOCK->nllen == 2 &&
                  *eptr == NLBLOCK->nl[0])
                {
                md->hitend = TRUE;
                if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
                }
              eptr++;
              ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
              }
            }

          /* Handle unlimited UTF-8 repeat */

          else
            {
            for (i = min; i < max; i++)
              {
              if (eptr >= md->end_subject)
                {
                SCHECK_PARTIAL();
                break;
                }
              if (IS_NEWLINE(eptr)) break;
              if (md->partial != 0 &&    /* Take care with CRLF partial */
                  eptr + 1 >= md->end_subject &&
                  NLBLOCK->nltype == NLTYPE_FIXED &&
                  NLBLOCK->nllen == 2 &&
                  *eptr == NLBLOCK->nl[0])
                {
                md->hitend = TRUE;
                if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
                }
              eptr++;
              ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
              }
            }
          break;

          case OP_ALLANY:
          if (max < INT_MAX)
            {
            for (i = min; i < max; i++)
              {
              if (eptr >= md->end_subject)
                {
                SCHECK_PARTIAL();
                break;
                }
              eptr++;
              ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
              }
            }
          else
            {
            eptr = md->end_subject;   /* Unlimited UTF-8 repeat */
            SCHECK_PARTIAL();
            }
          break;

          /* The byte case is the same as non-UTF8 */

          case OP_ANYBYTE:
          c = max - min;
          if (c > (unsigned int)(md->end_subject - eptr))
            {
            eptr = md->end_subject;
            SCHECK_PARTIAL();
            }
          else eptr += c;
          break;

          case OP_ANYNL:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c == 0x000d)
              {
              if (++eptr >= md->end_subject) break;
              if (*eptr == 0x000a) eptr++;
              }
            else
              {
              if (c != 0x000a &&
                  (md->bsr_anycrlf ||
                   (c != 0x000b && c != 0x000c &&
                    c != 0x0085 && c != 0x2028 && c != 0x2029)))
                break;
              eptr += len;
              }
            }
          break;

          case OP_NOT_HSPACE:
          case OP_HSPACE:
          for (i = min; i < max; i++)
            {
            BOOL gotspace;
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            switch(c)
              {
              default: gotspace = FALSE; break;
              case 0x09:      /* HT */
              case 0x20:      /* SPACE */
              case 0xa0:      /* NBSP */
              case 0x1680:    /* OGHAM SPACE MARK */
              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
              case 0x2000:    /* EN QUAD */
              case 0x2001:    /* EM QUAD */
              case 0x2002:    /* EN SPACE */
              case 0x2003:    /* EM SPACE */
              case 0x2004:    /* THREE-PER-EM SPACE */
              case 0x2005:    /* FOUR-PER-EM SPACE */
              case 0x2006:    /* SIX-PER-EM SPACE */
              case 0x2007:    /* FIGURE SPACE */
              case 0x2008:    /* PUNCTUATION SPACE */
              case 0x2009:    /* THIN SPACE */
              case 0x200A:    /* HAIR SPACE */
              case 0x202f:    /* NARROW NO-BREAK SPACE */
              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
              case 0x3000:    /* IDEOGRAPHIC SPACE */
              gotspace = TRUE;
              break;
              }
            if (gotspace == (ctype == OP_NOT_HSPACE)) break;
            eptr += len;
            }
          break;

          case OP_NOT_VSPACE:
          case OP_VSPACE:
          for (i = min; i < max; i++)
            {
            BOOL gotspace;
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            switch(c)
              {
              default: gotspace = FALSE; break;
              case 0x0a:      /* LF */
              case 0x0b:      /* VT */
              case 0x0c:      /* FF */
              case 0x0d:      /* CR */
              case 0x85:      /* NEL */
              case 0x2028:    /* LINE SEPARATOR */
              case 0x2029:    /* PARAGRAPH SEPARATOR */
              gotspace = TRUE;
              break;
              }
            if (gotspace == (ctype == OP_NOT_VSPACE)) break;
            eptr += len;
            }
          break;

          case OP_NOT_DIGIT:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;
            eptr+= len;
            }
          break;

          case OP_DIGIT:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;
            eptr+= len;
            }
          break;

          case OP_NOT_WHITESPACE:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;
            eptr+= len;
            }
          break;

          case OP_WHITESPACE:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;
            eptr+= len;
            }
          break;

          case OP_NOT_WORDCHAR:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;
            eptr+= len;
            }
          break;

          case OP_WORDCHAR:
          for (i = min; i < max; i++)
            {
            int len = 1;
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            GETCHARLEN(c, eptr, len);
            if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
            eptr+= len;
            }
          break;

          default:
          RRETURN(PCRE_ERROR_INTERNAL);
          }

        /* eptr is now past the end of the maximum run. If possessive, we are
        done (no backing up). Otherwise, match at this position; anything other
        than no match is immediately returned. For nomatch, back up one
        character, unless we are matching \R and the last thing matched was
        \r\n, in which case, back up two bytes. */

        if (possessive) continue;
        for(;;)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */
          BACKCHAR(eptr);
          if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' &&
              eptr[-1] == '\r') eptr--;
          }
        }
      else
#endif  /* SUPPORT_UTF */
      /* Not UTF mode */
        {
        switch(ctype)
          {
          case OP_ANY:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (IS_NEWLINE(eptr)) break;
            if (md->partial != 0 &&    /* Take care with CRLF partial */
                eptr + 1 >= md->end_subject &&
                NLBLOCK->nltype == NLTYPE_FIXED &&
                NLBLOCK->nllen == 2 &&
                *eptr == NLBLOCK->nl[0])
              {
              md->hitend = TRUE;
              if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
              }
            eptr++;
            }
          break;

          case OP_ALLANY:
          case OP_ANYBYTE:
          c = max - min;
          if (c > (unsigned int)(md->end_subject - eptr))
            {
            eptr = md->end_subject;
            SCHECK_PARTIAL();
            }
          else eptr += c;
          break;

          case OP_ANYNL:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            c = *eptr;
            if (c == 0x000d)
              {
              if (++eptr >= md->end_subject) break;
              if (*eptr == 0x000a) eptr++;
              }
            else
              {
              if (c != 0x000a && (md->bsr_anycrlf ||
                (c != 0x000b && c != 0x000c && c != 0x0085
#ifdef COMPILE_PCRE16
                && c != 0x2028 && c != 0x2029
#endif
                ))) break;
              eptr++;
              }
            }
          break;

          case OP_NOT_HSPACE:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            c = *eptr;
            if (c == 0x09 || c == 0x20 || c == 0xa0
#ifdef COMPILE_PCRE16
              || c == 0x1680 || c == 0x180e || (c >= 0x2000 && c <= 0x200A)
              || c == 0x202f || c == 0x205f || c == 0x3000
#endif
              ) break;
            eptr++;
            }
          break;

          case OP_HSPACE:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            c = *eptr;
            if (c != 0x09 && c != 0x20 && c != 0xa0
#ifdef COMPILE_PCRE16
              && c != 0x1680 && c != 0x180e && (c < 0x2000 || c > 0x200A)
              && c != 0x202f && c != 0x205f && c != 0x3000
#endif
              ) break;
            eptr++;
            }
          break;

          case OP_NOT_VSPACE:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            c = *eptr;
            if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85
#ifdef COMPILE_PCRE16
              || c == 0x2028 || c == 0x2029
#endif
              ) break;
            eptr++;
            }
          break;

          case OP_VSPACE:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            c = *eptr;
            if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85
#ifdef COMPILE_PCRE16
              && c != 0x2028 && c != 0x2029
#endif
              ) break;
            eptr++;
            }
          break;

          case OP_NOT_DIGIT:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break;
            eptr++;
            }
          break;

          case OP_DIGIT:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break;
            eptr++;
            }
          break;

          case OP_NOT_WHITESPACE:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break;
            eptr++;
            }
          break;

          case OP_WHITESPACE:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break;
            eptr++;
            }
          break;

          case OP_NOT_WORDCHAR:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break;
            eptr++;
            }
          break;

          case OP_WORDCHAR:
          for (i = min; i < max; i++)
            {
            if (eptr >= md->end_subject)
              {
              SCHECK_PARTIAL();
              break;
              }
            if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break;
            eptr++;
            }
          break;

          default:
          RRETURN(PCRE_ERROR_INTERNAL);
          }

        /* eptr is now past the end of the maximum run. If possessive, we are
        done (no backing up). Otherwise, match at this position; anything other
        than no match is immediately returned. For nomatch, back up one
        character (byte), unless we are matching \R and the last thing matched
        was \r\n, in which case, back up two bytes. */

        if (possessive) continue;
        while (eptr >= pp)
          {
          RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);
          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          eptr--;
          if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' &&
              eptr[-1] == '\r') eptr--;
          }
        }

      /* Get here if we can't make it match with any permitted repetitions */

      RRETURN(MATCH_NOMATCH);
      }
    /* Control never gets here */

    /* There's been some horrible disaster. Arrival here can only mean there is
    something seriously wrong in the code above or the OP_xxx definitions. */

    default:
    DPRINTF(("Unknown opcode %d\n", *ecode));
    RRETURN(PCRE_ERROR_UNKNOWN_OPCODE);
    }

  /* Do not stick any code in here without much thought; it is assumed
  that "continue" in the code above comes out to here to repeat the main
  loop. */

  }             /* End of main loop */
/* Control never reaches here */


/* When compiling to use the heap rather than the stack for recursive calls to
match(), the RRETURN() macro jumps here. The number that is saved in
frame->Xwhere indicates which label we actually want to return to. */

#ifdef NO_RECURSE
#define LBL(val) case val: goto L_RM##val;
HEAP_RETURN:
switch (frame->Xwhere)
  {
  LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8)
  LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)
  LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)
  LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)
  LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64)
  LBL(65) LBL(66)
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
  LBL(21)
#endif
#ifdef SUPPORT_UTF
  LBL(16) LBL(18) LBL(20)
  LBL(22) LBL(23) LBL(28) LBL(30)
  LBL(32) LBL(34) LBL(42) LBL(46)
#ifdef SUPPORT_UCP
  LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)
  LBL(59) LBL(60) LBL(61) LBL(62)
#endif  /* SUPPORT_UCP */
#endif  /* SUPPORT_UTF */
  default:
  DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));

printf("+++jump error in pcre match: label %d non-existent\n", frame->Xwhere);

  return PCRE_ERROR_INTERNAL;
  }
#undef LBL
#endif  /* NO_RECURSE */
}


/***************************************************************************
****************************************************************************
                   RECURSION IN THE match() FUNCTION

Undefine all the macros that were defined above to handle this. */

#ifdef NO_RECURSE
#undef eptr
#undef ecode
#undef mstart
#undef offset_top
#undef eptrb
#undef flags

#undef callpat
#undef charptr
#undef data
#undef next
#undef pp
#undef prev
#undef saved_eptr

#undef new_recursive

#undef cur_is_word
#undef condition
#undef prev_is_word

#undef ctype
#undef length
#undef max
#undef min
#undef number
#undef offset
#undef op
#undef save_capture_last
#undef save_offset1
#undef save_offset2
#undef save_offset3
#undef stacksave

#undef newptrb

#endif

/* These two are defined as macros in both cases */

#undef fc
#undef fi

/***************************************************************************
***************************************************************************/


#ifdef NO_RECURSE
/*************************************************
*          Release allocated heap frames         *
*************************************************/

/* This function releases all the allocated frames. The base frame is on the
machine stack, and so must not be freed.

Argument: the address of the base frame
Returns:  nothing
*/

static void
release_match_heapframes (heapframe *frame_base)
{
heapframe *nextframe = frame_base->Xnextframe;
while (nextframe != NULL)
  {
  heapframe *oldframe = nextframe;
  nextframe = nextframe->Xnextframe;
  (PUBL(stack_free))(oldframe);
  }
}
#endif


/*************************************************
*         Execute a Regular Expression           *
*************************************************/

/* This function applies a compiled re to a subject string and picks out
portions of the string if it matches. Two elements in the vector are set for
each substring: the offsets to the start and end of the substring.

Arguments:
  argument_re     points to the compiled expression
  extra_data      points to extra data or is NULL
  subject         points to the subject string
  length          length of subject string (may contain binary zeros)
  start_offset    where to start in the subject string
  options         option bits
  offsets         points to a vector of ints to be filled in with offsets
  offsetcount     the number of elements in the vector

Returns:          > 0 => success; value is the number of elements filled in
                  = 0 => success, but offsets is not big enough
                   -1 => failed to match
                 < -1 => some kind of unexpected problem
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
PCREXEC8(const pcre *argument_re, const pcre_extra *extra_data,
  PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
  int offsetcount)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
  PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
  int offsetcount)
#endif
{
int rc, ocount, arg_offset_max;
int newline;
BOOL using_temporary_offsets = FALSE;
BOOL anchored;
BOOL startline;
BOOL firstline;
BOOL utf;
BOOL has_first_char = FALSE;
BOOL has_req_char = FALSE;
pcre_uchar first_char = 0;
pcre_uchar first_char2 = 0;
pcre_uchar req_char = 0;
pcre_uchar req_char2 = 0;
match_data match_block;
match_data *md = &match_block;
const pcre_uint8 *tables;
const pcre_uint8 *start_bits = NULL;
PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset;
PCRE_PUCHAR end_subject;
PCRE_PUCHAR start_partial = NULL;
PCRE_PUCHAR req_char_ptr = start_match - 1;

const pcre_study_data *study;
const REAL_PCRE *re = (const REAL_PCRE *)argument_re;

#ifdef NO_RECURSE
heapframe frame_zero;
frame_zero.Xprevframe = NULL;            /* Marks the top level */
frame_zero.Xnextframe = NULL;            /* None are allocated yet */
md->match_frames_base = &frame_zero;
#endif

/* Check for the special magic call that measures the size of the stack used
per recursive call of match(). Without the funny casting for sizeof, a Windows
compiler gave this error: "unary minus operator applied to unsigned type,
result still unsigned". Hopefully the cast fixes that. */

if (re == NULL && extra_data == NULL && subject == NULL && length == -999 &&
    start_offset == -999)
#ifdef NO_RECURSE
  return -((int)sizeof(heapframe));
#else
  return match(NULL, NULL, NULL, 0, NULL, NULL, 0);
#endif

/* Plausibility checks */

if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0))
  return PCRE_ERROR_NULL;
if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;

/* Check that the first field in the block is the magic number. If it is not,
return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
means that the pattern is likely compiled with different endianness. */

if (re->magic_number != MAGIC_NUMBER)
  return re->magic_number == REVERSED_MAGIC_NUMBER?
    PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;

/* These two settings are used in the code for checking a UTF-8 string that
follows immediately afterwards. Other values in the md block are used only
during "normal" PCREXEC8() processing, not when the JIT support is in use,
so they are set up later. */

/* PCRE_UTF16 has the same value as PCRE_UTF8. */
utf = md->utf = (re->options & PCRE_UTF8) != 0;
md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 :
              ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0;

/* Check a UTF-8 string if required. Pass back the character offset and error
code for an invalid string if a results vector is available. */

#ifdef SUPPORT_UTF
if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
  {
  int erroroffset;
  int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset);
  if (errorcode != 0)
    {
    if (offsetcount >= 2)
      {
      offsets[0] = erroroffset;
      offsets[1] = errorcode;
      }
#ifdef COMPILE_PCRE16
    return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)?
      PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
#else
    return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?
      PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
#endif
    }

  /* Check that a start_offset points to the start of a UTF character. */
  if (start_offset > 0 && start_offset < length &&
      NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
    return PCRE_ERROR_BADUTF8_OFFSET;
  }
#endif

/* If the pattern was successfully studied with JIT support, run the JIT
executable instead of the rest of this function. Most options must be set at
compile time for the JIT code to be usable. Fallback to the normal code path if
an unsupported flag is set. */

#ifdef SUPPORT_JIT
if (extra_data != NULL
    && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT |
                             PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT
    && extra_data->executable_jit != NULL
    && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL |
                    PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART |
                    PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD)) == 0)
  {
  rc = PRIV(jit_exec)(re, extra_data, (const pcre_uchar *)subject, length,
       start_offset, options, offsets, offsetcount);

  /* PCRE_ERROR_NULL means that the selected normal or partial matching
  mode is not compiled. In this case we simply fallback to interpreter. */

  if (rc != PCRE_ERROR_NULL) return rc;
  }
#endif

/* Carry on with non-JIT matching. This information is for finding all the
numbers associated with a given name, for condition testing. */

md->name_table = (pcre_uchar *)re + re->name_table_offset;
md->name_count = re->name_count;
md->name_entry_size = re->name_entry_size;

/* Fish out the optional data from the extra_data structure, first setting
the default values. */

study = NULL;
md->match_limit = MATCH_LIMIT;
md->match_limit_recursion = MATCH_LIMIT_RECURSION;
md->callout_data = NULL;

/* The table pointer is always in native byte order. */

tables = re->tables;

if (extra_data != NULL)
  {
  register unsigned int flags = extra_data->flags;
  if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
    study = (const pcre_study_data *)extra_data->study_data;
  if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0)
    md->match_limit = extra_data->match_limit;
  if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
    md->match_limit_recursion = extra_data->match_limit_recursion;
  if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
    md->callout_data = extra_data->callout_data;
  if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;
  }

/* If the exec call supplied NULL for tables, use the inbuilt ones. This
is a feature that makes it possible to save compiled regex and re-use them
in other programs later. */

if (tables == NULL) tables = PRIV(default_tables);

/* Set up other data */

anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
startline = (re->flags & PCRE_STARTLINE) != 0;
firstline = (re->options & PCRE_FIRSTLINE) != 0;

/* The code starts after the real_pcre block and the capture name table. */

md->start_code = (const pcre_uchar *)re + re->name_table_offset +
  re->name_count * re->name_entry_size;

md->start_subject = (PCRE_PUCHAR)subject;
md->start_offset = start_offset;
md->end_subject = md->start_subject + length;
end_subject = md->end_subject;

md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
md->use_ucp = (re->options & PCRE_UCP) != 0;
md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
md->ignore_skip_arg = FALSE;

/* Some options are unpacked into BOOL variables in the hope that testing
them will be faster than individual option bits. */

md->notbol = (options & PCRE_NOTBOL) != 0;
md->noteol = (options & PCRE_NOTEOL) != 0;
md->notempty = (options & PCRE_NOTEMPTY) != 0;
md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;

md->hitend = FALSE;
md->mark = md->nomatch_mark = NULL;     /* In case never set */

md->recursive = NULL;                   /* No recursion at top level */
md->hasthen = (re->flags & PCRE_HASTHEN) != 0;

md->lcc = tables + lcc_offset;
md->fcc = tables + fcc_offset;
md->ctypes = tables + ctypes_offset;

/* Handle different \R options. */

switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
  {
  case 0:
  if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
    md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0;
  else
#ifdef BSR_ANYCRLF
  md->bsr_anycrlf = TRUE;
#else
  md->bsr_anycrlf = FALSE;
#endif
  break;

  case PCRE_BSR_ANYCRLF:
  md->bsr_anycrlf = TRUE;
  break;

  case PCRE_BSR_UNICODE:
  md->bsr_anycrlf = FALSE;
  break;

  default: return PCRE_ERROR_BADNEWLINE;
  }

/* Handle different types of newline. The three bits give eight cases. If
nothing is set at run time, whatever was used at compile time applies. */

switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options :
        (pcre_uint32)options) & PCRE_NEWLINE_BITS)
  {
  case 0: newline = NEWLINE; break;   /* Compile-time default */
  case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
  case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
  case PCRE_NEWLINE_CR+
       PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
  case PCRE_NEWLINE_ANY: newline = -1; break;
  case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
  default: return PCRE_ERROR_BADNEWLINE;
  }

if (newline == -2)
  {
  md->nltype = NLTYPE_ANYCRLF;
  }
else if (newline < 0)
  {
  md->nltype = NLTYPE_ANY;
  }
else
  {
  md->nltype = NLTYPE_FIXED;
  if (newline > 255)
    {
    md->nllen = 2;
    md->nl[0] = (newline >> 8) & 255;
    md->nl[1] = newline & 255;
    }
  else
    {
    md->nllen = 1;
    md->nl[0] = newline;
    }
  }

/* Partial matching was originally supported only for a restricted set of
regexes; from release 8.00 there are no restrictions, but the bits are still
defined (though never set). So there's no harm in leaving this code. */

if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)
  return PCRE_ERROR_BADPARTIAL;

/* If the expression has got more back references than the offsets supplied can
hold, we get a temporary chunk of working store to use during the matching.
Otherwise, we can use the vector supplied, rounding down its size to a multiple
of 3. */

ocount = offsetcount - (offsetcount % 3);
arg_offset_max = (2*ocount)/3;

if (re->top_backref > 0 && re->top_backref >= ocount/3)
  {
  ocount = re->top_backref * 3 + 3;
  md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int));
  if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
  using_temporary_offsets = TRUE;
  DPRINTF(("Got memory to hold back references\n"));
  }
else md->offset_vector = offsets;

md->offset_end = ocount;
md->offset_max = (2*ocount)/3;
md->offset_overflow = FALSE;
md->capture_last = -1;

/* Reset the working variable associated with each extraction. These should
never be used unless previously set, but they get saved and restored, and so we
initialize them to avoid reading uninitialized locations. Also, unset the
offsets for the matched string. This is really just for tidiness with callouts,
in case they inspect these fields. */

if (md->offset_vector != NULL)
  {
  register int *iptr = md->offset_vector + ocount;
  register int *iend = iptr - re->top_bracket;
  if (iend < md->offset_vector + 2) iend = md->offset_vector + 2;
  while (--iptr >= iend) *iptr = -1;
  md->offset_vector[0] = md->offset_vector[1] = -1;
  }

/* Set up the first character to match, if available. The first_char value is
never set for an anchored regular expression, but the anchoring may be forced
at run time, so we have to test for anchoring. The first char may be unset for
an unanchored pattern, of course. If there's no first char and the pattern was
studied, there may be a bitmap of possible first characters. */

if (!anchored)
  {
  if ((re->flags & PCRE_FIRSTSET) != 0)
    {
    has_first_char = TRUE;
    first_char = first_char2 = (pcre_uchar)(re->first_char);
    if ((re->flags & PCRE_FCH_CASELESS) != 0)
      {
      first_char2 = TABLE_GET(first_char, md->fcc, first_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
      if (utf && first_char > 127)
        first_char2 = UCD_OTHERCASE(first_char);
#endif
      }
    }
  else
    if (!startline && study != NULL &&
      (study->flags & PCRE_STUDY_MAPPED) != 0)
        start_bits = study->start_bits;
  }

/* For anchored or unanchored matches, there may be a "last known required
character" set. */

if ((re->flags & PCRE_REQCHSET) != 0)
  {
  has_req_char = TRUE;
  req_char = req_char2 = (pcre_uchar)(re->req_char);
  if ((re->flags & PCRE_RCH_CASELESS) != 0)
    {
    req_char2 = TABLE_GET(req_char, md->fcc, req_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
    if (utf && req_char > 127)
      req_char2 = UCD_OTHERCASE(req_char);
#endif
    }
  }


/* ==========================================================================*/

/* Loop for handling unanchored repeated matching attempts; for anchored regexs
the loop runs just once. */

for(;;)
  {
  PCRE_PUCHAR save_end_subject = end_subject;
  PCRE_PUCHAR new_start_match;

  /* If firstline is TRUE, the start of the match is constrained to the first
  line of a multiline string. That is, the match must be before or at the first
  newline. Implement this by temporarily adjusting end_subject so that we stop
  scanning at a newline. If the match fails at the newline, later code breaks
  this loop. */

  if (firstline)
    {
    PCRE_PUCHAR t = start_match;
#ifdef SUPPORT_UTF
    if (utf)
      {
      while (t < md->end_subject && !IS_NEWLINE(t))
        {
        t++;
        ACROSSCHAR(t < end_subject, *t, t++);
        }
      }
    else
#endif
    while (t < md->end_subject && !IS_NEWLINE(t)) t++;
    end_subject = t;
    }

  /* There are some optimizations that avoid running the match if a known
  starting point is not found, or if a known later character is not present.
  However, there is an option that disables these, for testing and for ensuring
  that all callouts do actually occur. The option can be set in the regex by
  (*NO_START_OPT) or passed in match-time options. */

  if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
    {
    /* Advance to a unique first char if there is one. */

    if (has_first_char)
      {
      if (first_char != first_char2)
        while (start_match < end_subject &&
            *start_match != first_char && *start_match != first_char2)
          start_match++;
      else
        while (start_match < end_subject && *start_match != first_char)
          start_match++;
      }

    /* Or to just after a linebreak for a multiline match */

    else if (startline)
      {
      if (start_match > md->start_subject + start_offset)
        {
#ifdef SUPPORT_UTF
        if (utf)
          {
          while (start_match < end_subject && !WAS_NEWLINE(start_match))
            {
            start_match++;
            ACROSSCHAR(start_match < end_subject, *start_match,
              start_match++);
            }
          }
        else
#endif
        while (start_match < end_subject && !WAS_NEWLINE(start_match))
          start_match++;

        /* If we have just passed a CR and the newline option is ANY or ANYCRLF,
        and we are now at a LF, advance the match position by one more character.
        */

        if (start_match[-1] == CHAR_CR &&
             (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
             start_match < end_subject &&
             *start_match == CHAR_NL)
          start_match++;
        }
      }

    /* Or to a non-unique first byte after study */

    else if (start_bits != NULL)
      {
      while (start_match < end_subject)
        {
        register unsigned int c = *start_match;
#ifndef COMPILE_PCRE8
        if (c > 255) c = 255;
#endif
        if ((start_bits[c/8] & (1 << (c&7))) == 0)
          {
          start_match++;
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
          /* In non 8-bit mode, the iteration will stop for
          characters > 255 at the beginning or not stop at all. */
          if (utf)
            ACROSSCHAR(start_match < end_subject, *start_match,
              start_match++);
#endif
          }
        else break;
        }
      }
    }   /* Starting optimizations */

  /* Restore fudged end_subject */

  end_subject = save_end_subject;

  /* The following two optimizations are disabled for partial matching or if
  disabling is explicitly requested. */

  if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial)
    {
    /* If the pattern was studied, a minimum subject length may be set. This is
    a lower bound; no actual string of that length may actually match the
    pattern. Although the value is, strictly, in characters, we treat it as
    bytes to avoid spending too much time in this optimization. */

    if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
        (pcre_uint32)(end_subject - start_match) < study->minlength)
      {
      rc = MATCH_NOMATCH;
      break;
      }

    /* If req_char is set, we know that that character must appear in the
    subject for the match to succeed. If the first character is set, req_char
    must be later in the subject; otherwise the test starts at the match point.
    This optimization can save a huge amount of backtracking in patterns with
    nested unlimited repeats that aren't going to match. Writing separate code
    for cased/caseless versions makes it go faster, as does using an
    autoincrement and backing off on a match.

    HOWEVER: when the subject string is very, very long, searching to its end
    can take a long time, and give bad performance on quite ordinary patterns.
    This showed up when somebody was matching something like /\d+C/ on a
    32-megabyte string... so we don't do this when the string is sufficiently
    long. */

    if (has_req_char && end_subject - start_match < REQ_BYTE_MAX)
      {
      register PCRE_PUCHAR p = start_match + (has_first_char? 1:0);

      /* We don't need to repeat the search if we haven't yet reached the
      place we found it at last time. */

      if (p > req_char_ptr)
        {
        if (req_char != req_char2)
          {
          while (p < end_subject)
            {
            register int pp = *p++;
            if (pp == req_char || pp == req_char2) { p--; break; }
            }
          }
        else
          {
          while (p < end_subject)
            {
            if (*p++ == req_char) { p--; break; }
            }
          }

        /* If we can't find the required character, break the matching loop,
        forcing a match failure. */

        if (p >= end_subject)
          {
          rc = MATCH_NOMATCH;
          break;
          }

        /* If we have found the required character, save the point where we
        found it, so that we don't search again next time round the loop if
        the start hasn't passed this character yet. */

        req_char_ptr = p;
        }
      }
    }

#ifdef PCRE_DEBUG  /* Sigh. Some compilers never learn. */
  printf(">>>> Match against: ");
  pchars(start_match, end_subject - start_match, TRUE, md);
  printf("\n");
#endif

  /* OK, we can now run the match. If "hitend" is set afterwards, remember the
  first starting point for which a partial match was found. */

  md->start_match_ptr = start_match;
  md->start_used_ptr = start_match;
  md->match_call_count = 0;
  md->match_function_type = 0;
  md->end_offset_top = 0;
  rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0);
  if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr;

  switch(rc)
    {
    /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched
    the SKIP's arg was not found. In this circumstance, Perl ignores the SKIP
    entirely. The only way we can do that is to re-do the match at the same
    point, with a flag to force SKIP with an argument to be ignored. Just
    treating this case as NOMATCH does not work because it does not check other
    alternatives in patterns such as A(*SKIP:A)B|AC when the subject is AC. */

    case MATCH_SKIP_ARG:
    new_start_match = start_match;
    md->ignore_skip_arg = TRUE;
    break;

    /* SKIP passes back the next starting point explicitly, but if it is the
    same as the match we have just done, treat it as NOMATCH. */

    case MATCH_SKIP:
    if (md->start_match_ptr != start_match)
      {
      new_start_match = md->start_match_ptr;
      break;
      }
    /* Fall through */

    /* NOMATCH and PRUNE advance by one character. THEN at this level acts
    exactly like PRUNE. Unset the ignore SKIP-with-argument flag. */

    case MATCH_NOMATCH:
    case MATCH_PRUNE:
    case MATCH_THEN:
    md->ignore_skip_arg = FALSE;
    new_start_match = start_match + 1;
#ifdef SUPPORT_UTF
    if (utf)
      ACROSSCHAR(new_start_match < end_subject, *new_start_match,
        new_start_match++);
#endif
    break;

    /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */

    case MATCH_COMMIT:
    rc = MATCH_NOMATCH;
    goto ENDLOOP;

    /* Any other return is either a match, or some kind of error. */

    default:
    goto ENDLOOP;
    }

  /* Control reaches here for the various types of "no match at this point"
  result. Reset the code to MATCH_NOMATCH for subsequent checking. */

  rc = MATCH_NOMATCH;

  /* If PCRE_FIRSTLINE is set, the match must happen before or at the first
  newline in the subject (though it may continue over the newline). Therefore,
  if we have just failed to match, starting at a newline, do not continue. */

  if (firstline && IS_NEWLINE(start_match)) break;

  /* Advance to new matching position */

  start_match = new_start_match;

  /* Break the loop if the pattern is anchored or if we have passed the end of
  the subject. */

  if (anchored || start_match > end_subject) break;

  /* If we have just passed a CR and we are now at a LF, and the pattern does
  not contain any explicit matches for \r or \n, and the newline option is CRLF
  or ANY or ANYCRLF, advance the match position by one more character. In
  normal matching start_match will aways be greater than the first position at
  this stage, but a failed *SKIP can cause a return at the same point, which is
  why the first test exists. */

  if (start_match > (PCRE_PUCHAR)subject + start_offset &&
      start_match[-1] == CHAR_CR &&
      start_match < end_subject &&
      *start_match == CHAR_NL &&
      (re->flags & PCRE_HASCRORLF) == 0 &&
        (md->nltype == NLTYPE_ANY ||
         md->nltype == NLTYPE_ANYCRLF ||
         md->nllen == 2))
    start_match++;

  md->mark = NULL;   /* Reset for start of next match attempt */
  }                  /* End of for(;;) "bumpalong" loop */

/* ==========================================================================*/

/* We reach here when rc is not MATCH_NOMATCH, or if one of the stopping
conditions is true:

(1) The pattern is anchored or the match was failed by (*COMMIT);

(2) We are past the end of the subject;

(3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because
    this option requests that a match occur at or before the first newline in
    the subject.

When we have a match and the offset vector is big enough to deal with any
backreferences, captured substring offsets will already be set up. In the case
where we had to get some local store to hold offsets for backreference
processing, copy those that we can. In this case there need not be overflow if
certain parts of the pattern were not used, even though there are more
capturing parentheses than vector slots. */

ENDLOOP:

if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
  {
  if (using_temporary_offsets)
    {
    if (arg_offset_max >= 4)
      {
      memcpy(offsets + 2, md->offset_vector + 2,
        (arg_offset_max - 2) * sizeof(int));
      DPRINTF(("Copied offsets from temporary memory\n"));
      }
    if (md->end_offset_top > arg_offset_max) md->offset_overflow = TRUE;
    DPRINTF(("Freeing temporary memory\n"));
    (PUBL(free))(md->offset_vector);
    }

  /* Set the return code to the number of captured strings, or 0 if there were
  too many to fit into the vector. */

  rc = (md->offset_overflow && md->end_offset_top >= arg_offset_max)?
    0 : md->end_offset_top/2;

  /* If there is space in the offset vector, set any unused pairs at the end of
  the pattern to -1 for backwards compatibility. It is documented that this
  happens. In earlier versions, the whole set of potential capturing offsets
  was set to -1 each time round the loop, but this is handled differently now.
  "Gaps" are set to -1 dynamically instead (this fixes a bug). Thus, it is only
  those at the end that need unsetting here. We can't just unset them all at
  the start of the whole thing because they may get set in one branch that is
  not the final matching branch. */

  if (md->end_offset_top/2 <= re->top_bracket && offsets != NULL)
    {
    register int *iptr, *iend;
    int resetcount = 2 + re->top_bracket * 2;
    if (resetcount > offsetcount) resetcount = offsetcount;
    iptr = offsets + md->end_offset_top;
    iend = offsets + resetcount;
    while (iptr < iend) *iptr++ = -1;
    }

  /* If there is space, set up the whole thing as substring 0. The value of
  md->start_match_ptr might be modified if \K was encountered on the success
  matching path. */

  if (offsetcount < 2) rc = 0; else
    {
    offsets[0] = (int)(md->start_match_ptr - md->start_subject);
    offsets[1] = (int)(md->end_match_ptr - md->start_subject);
    }

  /* Return MARK data if requested */

  if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
    *(extra_data->mark) = (pcre_uchar *)md->mark;
  DPRINTF((">>>> returning %d\n", rc));
#ifdef NO_RECURSE
  release_match_heapframes(&frame_zero);
#endif
  return rc;
  }

/* Control gets here if there has been an error, or if the overall match
attempt has failed at all permitted starting positions. */

if (using_temporary_offsets)
  {
  DPRINTF(("Freeing temporary memory\n"));
  (PUBL(free))(md->offset_vector);
  }

/* For anything other than nomatch or partial match, just return the code. */

if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
  {
  DPRINTF((">>>> error: returning %d\n", rc));
#ifdef NO_RECURSE
  release_match_heapframes(&frame_zero);
#endif
  return rc;
  }

/* Handle partial matches - disable any mark data */

if (start_partial != NULL)
  {
  DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
  md->mark = NULL;
  if (offsetcount > 1)
    {
    offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject);
    offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
    }
  rc = PCRE_ERROR_PARTIAL;
  }

/* This is the classic nomatch case */

else
  {
  DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
  rc = PCRE_ERROR_NOMATCH;
  }

/* Return the MARK data if it has been requested. */

if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
  *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark;
#ifdef NO_RECURSE
  release_match_heapframes(&frame_zero);
#endif
return rc;
}

/* End of PCREXEC8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_exec.c converted to PCREXEC8*/
/*autoconv-0013 PCREXEC8 line: 40 pcre_exec replaced by PCREXEC8*/
/*autoconv-0010 PCREXEC8 line: 45 added HAVE_CONFIG_H*/
/*autoconv-0011 PCREXEC8 line: 48 config.h replaced by CONFIG.h*/
/*autoconv-0011 PCREXEC8 line: 55 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 PCREXEC8 line: 6344 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREXEC8 line: 6419 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREXEC8 line: 7152 pcre_exec replaced by PCREXEC8*/
./ ADD NAME=STRINGCC 
// Copyright 2003 and onwards Google Inc.
// Author: Sanjay Ghemawat

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <stdio.h>
#include <map>
#include <algorithm>    // for make_pair

#include "CPPH.h"
#include "pcre_stringpiece.h"

// CHECK dies with a fatal error if condition is not true.  It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.  Therefore, it is safe to do things like:
//    CHECK(fp->Write(x) == 4)
#define CHECK(condition) do {                           \
  if (!(condition)) {                                   \
    fprintf(stderr, "%s:%d: Check failed: %s\n",        \
            __FILE__, __LINE__, #condition);            \
    exit(1);                                            \
  }                                                     \
} while (0)

using PCRECPP::StringPiece;

static void CheckSTLComparator() {
  string s1("foo");
  string s2("bar");
  string s3("baz");

  StringPiece p1(s1);
  StringPiece p2(s2);
  StringPiece p3(s3);

  typedef std::map<StringPiece, int> TestMap;
  TestMap map;

  map.insert(std::make_pair(p1, 0));
  map.insert(std::make_pair(p2, 1));
  map.insert(std::make_pair(p3, 2));

  CHECK(map.size() == 3);

  TestMap::const_iterator iter = map.begin();
  CHECK(iter->second == 1);
  ++iter;
  CHECK(iter->second == 2);
  ++iter;
  CHECK(iter->second == 0);
  ++iter;
  CHECK(iter == map.end());

  TestMap::iterator new_iter = map.find("zot");
  CHECK(new_iter == map.end());

  new_iter = map.find("bar");
  CHECK(new_iter != map.end());

  map.erase(new_iter);
  CHECK(map.size() == 2);

  iter = map.begin();
  CHECK(iter->second == 2);
  ++iter;
  CHECK(iter->second == 0);
  ++iter;
  CHECK(iter == map.end());
}

static void CheckComparisonOperators() {
#define CMP_Y(op, x, y)                                         \
  CHECK( (StringPiece((x)) op StringPiece((y))));               \
  CHECK( (StringPiece((x)).compare(StringPiece((y))) op 0))

#define CMP_N(op, x, y)                                         \
  CHECK(!(StringPiece((x)) op StringPiece((y))));               \
  CHECK(!(StringPiece((x)).compare(StringPiece((y))) op 0))

  CMP_Y(==, "",   "");
  CMP_Y(==, "a",  "a");
  CMP_Y(==, "aa", "aa");
  CMP_N(==, "a",  "");
  CMP_N(==, "",   "a");
  CMP_N(==, "a",  "b");
  CMP_N(==, "a",  "aa");
  CMP_N(==, "aa", "a");

  CMP_N(!=, "",   "");
  CMP_N(!=, "a",  "a");
  CMP_N(!=, "aa", "aa");
  CMP_Y(!=, "a",  "");
  CMP_Y(!=, "",   "a");
  CMP_Y(!=, "a",  "b");
  CMP_Y(!=, "a",  "aa");
  CMP_Y(!=, "aa", "a");

  CMP_Y(<, "a",  "b");
  CMP_Y(<, "a",  "aa");
  CMP_Y(<, "aa", "b");
  CMP_Y(<, "aa", "bb");
  CMP_N(<, "a",  "a");
  CMP_N(<, "b",  "a");
  CMP_N(<, "aa", "a");
  CMP_N(<, "b",  "aa");
  CMP_N(<, "bb", "aa");

  CMP_Y(<=, "a",  "a");
  CMP_Y(<=, "a",  "b");
  CMP_Y(<=, "a",  "aa");
  CMP_Y(<=, "aa", "b");
  CMP_Y(<=, "aa", "bb");
  CMP_N(<=, "b",  "a");
  CMP_N(<=, "aa", "a");
  CMP_N(<=, "b",  "aa");
  CMP_N(<=, "bb", "aa");

  CMP_N(>=, "a",  "b");
  CMP_N(>=, "a",  "aa");
  CMP_N(>=, "aa", "b");
  CMP_N(>=, "aa", "bb");
  CMP_Y(>=, "a",  "a");
  CMP_Y(>=, "b",  "a");
  CMP_Y(>=, "aa", "a");
  CMP_Y(>=, "b",  "aa");
  CMP_Y(>=, "bb", "aa");

  CMP_N(>, "a",  "a");
  CMP_N(>, "a",  "b");
  CMP_N(>, "a",  "aa");
  CMP_N(>, "aa", "b");
  CMP_N(>, "aa", "bb");
  CMP_Y(>, "b",  "a");
  CMP_Y(>, "aa", "a");
  CMP_Y(>, "b",  "aa");
  CMP_Y(>, "bb", "aa");

#undef CMP_Y
#undef CMP_N
}

int main(int argc, char** argv) {
  CheckComparisonOperators();
  CheckSTLComparator();

  printf("OK\n");
  return 0;
}
/*autoconv-0001 C:\projects\pcre-8.31\pcre_stringpiece_unittest.cc converted to STRINGCC*/
/*autoconv-0010 STRINGCC line: 5 added HAVE_CONFIG_H*/
/*autoconv-0011 STRINGCC line: 8 config.h replaced by CONFIG.h*/
/*autoconv-0011 STRINGCC line: 15 pcrecpp.h replaced by CPPH.h*/
/*autoconv-0013 STRINGCC line: 30 pcrecpp replaced by PCRECPP*/
./ ADD NAME=NEWLINE8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains internal functions for testing newlines when more than
one kind of newline is to be recognized. When a newline is found, its length is
returned. In principle, we could implement several newline "types", each
referring to a different set of newline characters. At present, PCRE supports
only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF,
and NLTYPE_ANY. The full list of Unicode newline characters is taken from
http://unicode.org/unicode/reports/tr18/. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"



/*************************************************
*      Check for newline at given position       *
*************************************************/

/* It is guaranteed that the initial value of ptr is less than the end of the
string that is being processed.

Arguments:
  ptr          pointer to possible newline
  type         the newline type
  endptr       pointer to the end of the string
  lenptr       where to return the length
  utf          TRUE if in utf mode

Returns:       TRUE or FALSE
*/

BOOL
PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr,
  BOOL utf)
{
int c;
(void)utf;
#ifdef SUPPORT_UTF
if (utf)
  {
  GETCHAR(c, ptr);
  }
else
#endif  /* SUPPORT_UTF */
  c = *ptr;

if (type == NLTYPE_ANYCRLF) switch(c)
  {
  case 0x000a: *lenptr = 1; return TRUE;             /* LF */
  case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
               return TRUE;                          /* CR */
  default: return FALSE;
  }

/* NLTYPE_ANY */

else switch(c)
  {
  case 0x000a:                                       /* LF */
  case 0x000b:                                       /* VT */
  case 0x000c: *lenptr = 1; return TRUE;             /* FF */
  case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
               return TRUE;                          /* CR */
#ifdef COMPILE_PCRE8
  case 0x0085: *lenptr = utf? 2 : 1; return TRUE;    /* NEL */
  case 0x2028:                                       /* LS */
  case 0x2029: *lenptr = 3; return TRUE;             /* PS */
#else
  case 0x0085:                                       /* NEL */
  case 0x2028:                                       /* LS */
  case 0x2029: *lenptr = 1; return TRUE;             /* PS */
#endif /* COMPILE_PCRE8 */
  default: return FALSE;
  }
}



/*************************************************
*     Check for newline at previous position     *
*************************************************/

/* It is guaranteed that the initial value of ptr is greater than the start of
the string that is being processed.

Arguments:
  ptr          pointer to possible newline
  type         the newline type
  startptr     pointer to the start of the string
  lenptr       where to return the length
  utf          TRUE if in utf mode

Returns:       TRUE or FALSE
*/

BOOL
PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr,
  BOOL utf)
{
int c;
(void)utf;
ptr--;
#ifdef SUPPORT_UTF
if (utf)
  {
  BACKCHAR(ptr);
  GETCHAR(c, ptr);
  }
else
#endif  /* SUPPORT_UTF */
  c = *ptr;

if (type == NLTYPE_ANYCRLF) switch(c)
  {
  case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
               return TRUE;                         /* LF */
  case 0x000d: *lenptr = 1; return TRUE;            /* CR */
  default: return FALSE;
  }

else switch(c)
  {
  case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
               return TRUE;                         /* LF */
  case 0x000b:                                      /* VT */
  case 0x000c:                                      /* FF */
  case 0x000d: *lenptr = 1; return TRUE;            /* CR */
#ifdef COMPILE_PCRE8
  case 0x0085: *lenptr = utf? 2 : 1; return TRUE;   /* NEL */
  case 0x2028:                                      /* LS */
  case 0x2029: *lenptr = 3; return TRUE;            /* PS */
#else
  case 0x0085:                                       /* NEL */
  case 0x2028:                                       /* LS */
  case 0x2029: *lenptr = 1; return TRUE;             /* PS */
#endif /* COMPILE_PCRE8 */
  default: return FALSE;
  }
}

/* End of NEWLINE8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_newline.c converted to NEWLINE8*/
/*autoconv-0010 NEWLINE8 line: 51 added HAVE_CONFIG_H*/
/*autoconv-0011 NEWLINE8 line: 54 config.h replaced by CONFIG.h*/
/*autoconv-0011 NEWLINE8 line: 57 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 NEWLINE8 line: 187 pcre_newline replaced by NEWLINE8*/
./ ADD NAME=CPPH 
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sanjay Ghemawat
// Support for PCRE_XXX modifiers added by Giuseppe Maxia, July 2005

#ifndef _PCRECPP_H
#define _PCRECPP_H

// C++ interface to the pcre regular-expression library.  RE supports
// Perl-style regular expressions (with extensions like \d, \w, \s,
// ...).
//
// -----------------------------------------------------------------------
// REGEXP SYNTAX:
//
// This module is part of the pcre library and hence supports its syntax
// for regular expressions.
//
// The syntax is pretty similar to Perl's.  For those not familiar
// with Perl's regular expressions, here are some examples of the most
// commonly used extensions:
//
//   "hello (\\w+) world"  -- \w matches a "word" character
//   "version (\\d+)"      -- \d matches a digit
//   "hello\\s+world"      -- \s matches any whitespace character
//   "\\b(\\w+)\\b"        -- \b matches empty string at a word boundary
//   "(?i)hello"           -- (?i) turns on case-insensitive matching
//   "/\\*(.*?)\\*/"       -- .*? matches . minimum no. of times possible
//
// -----------------------------------------------------------------------
// MATCHING INTERFACE:
//
// The "FullMatch" operation checks that supplied text matches a
// supplied pattern exactly.
//
// Example: successful match
//    PCRECPP::RE re("h.*o");
//    re.FullMatch("hello");
//
// Example: unsuccessful match (requires full match):
//    PCRECPP::RE re("e");
//    !re.FullMatch("hello");
//
// Example: creating a temporary RE object:
//    PCRECPP::RE("h.*o").FullMatch("hello");
//
// You can pass in a "const char*" or a "string" for "text".  The
// examples below tend to use a const char*.
//
// You can, as in the different examples above, store the RE object
// explicitly in a variable or use a temporary RE object.  The
// examples below use one mode or the other arbitrarily.  Either
// could correctly be used for any of these examples.
//
// -----------------------------------------------------------------------
// MATCHING WITH SUB-STRING EXTRACTION:
//
// You can supply extra pointer arguments to extract matched subpieces.
//
// Example: extracts "ruby" into "s" and 1234 into "i"
//    int i;
//    string s;
//    PCRECPP::RE re("(\\w+):(\\d+)");
//    re.FullMatch("ruby:1234", &s, &i);
//
// Example: does not try to extract any extra sub-patterns
//    re.FullMatch("ruby:1234", &s);
//
// Example: does not try to extract into NULL
//    re.FullMatch("ruby:1234", NULL, &i);
//
// Example: integer overflow causes failure
//    !re.FullMatch("ruby:1234567891234", NULL, &i);
//
// Example: fails because there aren't enough sub-patterns:
//    !PCRECPP::RE("\\w+:\\d+").FullMatch("ruby:1234", &s);
//
// Example: fails because string cannot be stored in integer
//    !PCRECPP::RE("(.*)").FullMatch("ruby", &i);
//
// The provided pointer arguments can be pointers to any scalar numeric
// type, or one of
//    string        (matched piece is copied to string)
//    StringPiece   (StringPiece is mutated to point to matched piece)
//    T             (where "bool T::ParseFrom(const char*, int)" exists)
//    NULL          (the corresponding matched sub-pattern is not copied)
//
// CAVEAT: An optional sub-pattern that does not exist in the matched
// string is assigned the empty string.  Therefore, the following will
// return false (because the empty string is not a valid number):
//    int number;
//    PCRECPP::RE::FullMatch("abc", "[a-z]+(\\d+)?", &number);
//
// -----------------------------------------------------------------------
// DO_MATCH
//
// The matching interface supports at most 16 arguments per call.
// If you need more, consider using the more general interface
// PCRECPP::RE::DoMatch().  See PCRECPP.h for the signature for DoMatch.
//
// -----------------------------------------------------------------------
// PARTIAL MATCHES
//
// You can use the "PartialMatch" operation when you want the pattern
// to match any substring of the text.
//
// Example: simple search for a string:
//    PCRECPP::RE("ell").PartialMatch("hello");
//
// Example: find first number in a string:
//    int number;
//    PCRECPP::RE re("(\\d+)");
//    re.PartialMatch("x*100 + 20", &number);
//    assert(number == 100);
//
// -----------------------------------------------------------------------
// UTF-8 AND THE MATCHING INTERFACE:
//
// By default, pattern and text are plain text, one byte per character.
// The UTF8 flag, passed to the constructor, causes both pattern
// and string to be treated as UTF-8 text, still a byte stream but
// potentially multiple bytes per character. In practice, the text
// is likelier to be UTF-8 than the pattern, but the match returned
// may depend on the UTF8 flag, so always use it when matching
// UTF8 text.  E.g., "." will match one byte normally but with UTF8
// set may match up to three bytes of a multi-byte character.
//
// Example:
//    PCRECPP::RE_Options options;
//    options.set_utf8();
//    PCRECPP::RE re(utf8_pattern, options);
//    re.FullMatch(utf8_string);
//
// Example: using the convenience function UTF8():
//    PCRECPP::RE re(utf8_pattern, PCRECPP::UTF8());
//    re.FullMatch(utf8_string);
//
// NOTE: The UTF8 option is ignored if pcre was not configured with the
//       --enable-utf8 flag.
//
// -----------------------------------------------------------------------
// PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE
//
// PCRE defines some modifiers to change the behavior of the regular
// expression engine.
// The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle
// to pass such modifiers to a RE class.
//
// Currently, the following modifiers are supported
//
//    modifier              description               Perl corresponding
//
//    PCRE_CASELESS         case insensitive match    /i
//    PCRE_MULTILINE        multiple lines match      /m
//    PCRE_DOTALL           dot matches newlines      /s
//    PCRE_DOLLAR_ENDONLY   $ matches only at end     N/A
//    PCRE_EXTRA            strict escape parsing     N/A
//    PCRE_EXTENDED         ignore whitespaces        /x
//    PCRE_UTF8             handles UTF8 chars        built-in
//    PCRE_UNGREEDY         reverses * and *?         N/A
//    PCRE_NO_AUTO_CAPTURE  disables matching parens  N/A (*)
//
// (For a full account on how each modifier works, please check the
// PCRE API reference manual).
//
// (*) Both Perl and PCRE allow non matching parentheses by means of the
// "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not
// capture, while (ab|cd) does.
//
// For each modifier, there are two member functions whose name is made
// out of the modifier in lowercase, without the "PCRE_" prefix. For
// instance, PCRE_CASELESS is handled by
//    bool caseless(),
// which returns true if the modifier is set, and
//    RE_Options & set_caseless(bool),
// which sets or unsets the modifier.
//
// Moreover, PCRE_EXTRA_MATCH_LIMIT can be accessed through the
// set_match_limit() and match_limit() member functions.
// Setting match_limit to a non-zero value will limit the executation of
// pcre to keep it from doing bad things like blowing the stack or taking
// an eternity to return a result.  A value of 5000 is good enough to stop
// stack blowup in a 2MB thread stack.  Setting match_limit to zero will
// disable match limiting.  Alternately, you can set match_limit_recursion()
// which uses PCRE_EXTRA_MATCH_LIMIT_RECURSION to limit how much pcre
// recurses.  match_limit() caps the number of matches pcre does;
// match_limit_recrusion() caps the depth of recursion.
//
// Normally, to pass one or more modifiers to a RE class, you declare
// a RE_Options object, set the appropriate options, and pass this
// object to a RE constructor. Example:
//
//    RE_options opt;
//    opt.set_caseless(true);
//
//    if (RE("HELLO", opt).PartialMatch("hello world")) ...
//
// RE_options has two constructors. The default constructor takes no
// arguments and creates a set of flags that are off by default.
//
// The optional parameter 'option_flags' is to facilitate transfer
// of legacy code from C programs.  This lets you do
//    RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str);
//
// But new code is better off doing
//    RE(pattern,
//      RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str);
// (See below)
//
// If you are going to pass one of the most used modifiers, there are some
// convenience functions that return a RE_Options class with the
// appropriate modifier already set:
// CASELESS(), UTF8(), MULTILINE(), DOTALL(), EXTENDED()
//
// If you need to set several options at once, and you don't want to go
// through the pains of declaring a RE_Options object and setting several
// options, there is a parallel method that give you such ability on the
// fly. You can concatenate several set_xxxxx member functions, since each
// of them returns a reference to its class object.  e.g.: to pass
// PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one
// statement, you may write
//
//    RE("  xyz \\s+ .* blah$", RE_Options()
//                            .set_caseless(true)
//                            .set_extended(true)
//                            .set_multiline(true)).PartialMatch(sometext);
//
// -----------------------------------------------------------------------
// SCANNING TEXT INCREMENTALLY
//
// The "Consume" operation may be useful if you want to repeatedly
// match regular expressions at the front of a string and skip over
// them as they match.  This requires use of the "StringPiece" type,
// which represents a sub-range of a real string.  Like RE, StringPiece
// is defined in the PCRECPP namespace.
//
// Example: read lines of the form "var = value" from a string.
//    string contents = ...;                 // Fill string somehow
//    PCRECPP::StringPiece input(contents);  // Wrap in a StringPiece
//
//    string var;
//    int value;
//    PCRECPP::RE re("(\\w+) = (\\d+)\n");
//    while (re.Consume(&input, &var, &value)) {
//      ...;
//    }
//
// Each successful call to "Consume" will set "var/value", and also
// advance "input" so it points past the matched text.
//
// The "FindAndConsume" operation is similar to "Consume" but does not
// anchor your match at the beginning of the string.  For example, you
// could extract all words from a string by repeatedly calling
//     PCRECPP::RE("(\\w+)").FindAndConsume(&input, &word)
//
// -----------------------------------------------------------------------
// PARSING HEX/OCTAL/C-RADIX NUMBERS
//
// By default, if you pass a pointer to a numeric value, the
// corresponding text is interpreted as a base-10 number.  You can
// instead wrap the pointer with a call to one of the operators Hex(),
// Octal(), or CRadix() to interpret the text in another base.  The
// CRadix operator interprets C-style "0" (base-8) and "0x" (base-16)
// prefixes, but defaults to base-10.
//
// Example:
//   int a, b, c, d;
//   PCRECPP::RE re("(.*) (.*) (.*) (.*)");
//   re.FullMatch("100 40 0100 0x40",
//                PCRECPP::Octal(&a), PCRECPP::Hex(&b),
//                PCRECPP::CRadix(&c), PCRECPP::CRadix(&d));
// will leave 64 in a, b, c, and d.
//
// -----------------------------------------------------------------------
// REPLACING PARTS OF STRINGS
//
// You can replace the first match of "pattern" in "str" with
// "rewrite".  Within "rewrite", backslash-escaped digits (\1 to \9)
// can be used to insert text matching corresponding parenthesized
// group from the pattern.  \0 in "rewrite" refers to the entire
// matching text.  E.g.,
//
//   string s = "yabba dabba doo";
//   PCRECPP::RE("b+").Replace("d", &s);
//
// will leave "s" containing "yada dabba doo".  The result is true if
// the pattern matches and a replacement occurs, or false otherwise.
//
// GlobalReplace() is like Replace(), except that it replaces all
// occurrences of the pattern in the string with the rewrite.
// Replacements are not subject to re-matching.  E.g.,
//
//   string s = "yabba dabba doo";
//   PCRECPP::RE("b+").GlobalReplace("d", &s);
//
// will leave "s" containing "yada dada doo".  It returns the number
// of replacements made.
//
// Extract() is like Replace(), except that if the pattern matches,
// "rewrite" is copied into "out" (an additional argument) with
// substitutions.  The non-matching portions of "text" are ignored.
// Returns true iff a match occurred and the extraction happened
// successfully.  If no match occurs, the string is left unaffected.


#include <string>
#include "PCRE.h"
#include <pcrecpparg.h>   // defines the Arg class
// This isn't technically needed here, but we include it
// anyway so folks who include PCRECPP.h don't have to.
#include <pcre_stringpiece.h>

namespace PCRECPP {

#define PCRE_SET_OR_CLEAR(b, o) \
    if (b) all_options_ |= (o); else all_options_ &= ~(o); \
    return *this

#define PCRE_IS_SET(o)  \
        (all_options_ & o) == o

/***** Compiling regular expressions: the RE class *****/

// RE_Options allow you to set options to be passed along to pcre,
// along with other options we put on top of pcre.
// Only 9 modifiers, plus match_limit and match_limit_recursion,
// are supported now.
class PCRECPP_EXP_DEFN RE_Options {
 public:
  // constructor
  RE_Options() : match_limit_(0), match_limit_recursion_(0), all_options_(0) {}

  // alternative constructor.
  // To facilitate transfer of legacy code from C programs
  //
  // This lets you do
  //    RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str);
  // But new code is better off doing
  //    RE(pattern,
  //      RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str);
  RE_Options(int option_flags) : match_limit_(0), match_limit_recursion_(0),
                                 all_options_(option_flags) {}
  // we're fine with the default destructor, copy constructor, etc.

  // accessors and mutators
  int match_limit() const { return match_limit_; };
  RE_Options &set_match_limit(int limit) {
    match_limit_ = limit;
    return *this;
  }

  int match_limit_recursion() const { return match_limit_recursion_; };
  RE_Options &set_match_limit_recursion(int limit) {
    match_limit_recursion_ = limit;
    return *this;
  }

  bool caseless() const {
    return PCRE_IS_SET(PCRE_CASELESS);
  }
  RE_Options &set_caseless(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_CASELESS);
  }

  bool multiline() const {
    return PCRE_IS_SET(PCRE_MULTILINE);
  }
  RE_Options &set_multiline(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_MULTILINE);
  }

  bool dotall() const {
    return PCRE_IS_SET(PCRE_DOTALL);
  }
  RE_Options &set_dotall(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_DOTALL);
  }

  bool extended() const {
    return PCRE_IS_SET(PCRE_EXTENDED);
  }
  RE_Options &set_extended(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_EXTENDED);
  }

  bool dollar_endonly() const {
    return PCRE_IS_SET(PCRE_DOLLAR_ENDONLY);
  }
  RE_Options &set_dollar_endonly(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_DOLLAR_ENDONLY);
  }

  bool extra() const {
    return PCRE_IS_SET(PCRE_EXTRA);
  }
  RE_Options &set_extra(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_EXTRA);
  }

  bool ungreedy() const {
    return PCRE_IS_SET(PCRE_UNGREEDY);
  }
  RE_Options &set_ungreedy(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_UNGREEDY);
  }

  bool utf8() const {
    return PCRE_IS_SET(PCRE_UTF8);
  }
  RE_Options &set_utf8(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_UTF8);
  }

  bool no_auto_capture() const {
    return PCRE_IS_SET(PCRE_NO_AUTO_CAPTURE);
  }
  RE_Options &set_no_auto_capture(bool x) {
    PCRE_SET_OR_CLEAR(x, PCRE_NO_AUTO_CAPTURE);
  }

  RE_Options &set_all_options(int opt) {
    all_options_ = opt;
    return *this;
  }
  int all_options() const {
    return all_options_ ;
  }

  // TODO: add other pcre flags

 private:
  int match_limit_;
  int match_limit_recursion_;
  int all_options_;
};

// These functions return some common RE_Options
static inline RE_Options UTF8() {
  return RE_Options().set_utf8(true);
}

static inline RE_Options CASELESS() {
  return RE_Options().set_caseless(true);
}
static inline RE_Options MULTILINE() {
  return RE_Options().set_multiline(true);
}

static inline RE_Options DOTALL() {
  return RE_Options().set_dotall(true);
}

static inline RE_Options EXTENDED() {
  return RE_Options().set_extended(true);
}

// Interface for regular expression matching.  Also corresponds to a
// pre-compiled regular expression.  An "RE" object is safe for
// concurrent use by multiple threads.
class PCRECPP_EXP_DEFN RE {
 public:
  // We provide implicit conversions from strings so that users can
  // pass in a string or a "const char*" wherever an "RE" is expected.
  RE(const string& pat) { Init(pat, NULL); }
  RE(const string& pat, const RE_Options& option) { Init(pat, &option); }
  RE(const char* pat) { Init(pat, NULL); }
  RE(const char* pat, const RE_Options& option) { Init(pat, &option); }
  RE(const unsigned char* pat) {
    Init(reinterpret_cast<const char*>(pat), NULL);
  }
  RE(const unsigned char* pat, const RE_Options& option) {
    Init(reinterpret_cast<const char*>(pat), &option);
  }

  // Copy constructor & assignment - note that these are expensive
  // because they recompile the expression.
  RE(const RE& re) { Init(re.pattern_, &re.options_); }
  const RE& operator=(const RE& re) {
    if (this != &re) {
      Cleanup();

      // This is the code that originally came from Google
      // Init(re.pattern_.c_str(), &re.options_);

      // This is the replacement from Ari Pollak
      Init(re.pattern_, &re.options_);
    }
    return *this;
  }


  ~RE();

  // The string specification for this RE.  E.g.
  //   RE re("ab*c?d+");
  //   re.pattern();    // "ab*c?d+"
  const string& pattern() const { return pattern_; }

  // If RE could not be created properly, returns an error string.
  // Else returns the empty string.
  const string& error() const { return *error_; }

  /***** The useful part: the matching interface *****/

  // This is provided so one can do pattern.ReplaceAll() just as
  // easily as ReplaceAll(pattern-text, ....)

  bool FullMatch(const StringPiece& text,
                 const Arg& ptr1 = no_arg,
                 const Arg& ptr2 = no_arg,
                 const Arg& ptr3 = no_arg,
                 const Arg& ptr4 = no_arg,
                 const Arg& ptr5 = no_arg,
                 const Arg& ptr6 = no_arg,
                 const Arg& ptr7 = no_arg,
                 const Arg& ptr8 = no_arg,
                 const Arg& ptr9 = no_arg,
                 const Arg& ptr10 = no_arg,
                 const Arg& ptr11 = no_arg,
                 const Arg& ptr12 = no_arg,
                 const Arg& ptr13 = no_arg,
                 const Arg& ptr14 = no_arg,
                 const Arg& ptr15 = no_arg,
                 const Arg& ptr16 = no_arg) const;

  bool PartialMatch(const StringPiece& text,
                    const Arg& ptr1 = no_arg,
                    const Arg& ptr2 = no_arg,
                    const Arg& ptr3 = no_arg,
                    const Arg& ptr4 = no_arg,
                    const Arg& ptr5 = no_arg,
                    const Arg& ptr6 = no_arg,
                    const Arg& ptr7 = no_arg,
                    const Arg& ptr8 = no_arg,
                    const Arg& ptr9 = no_arg,
                    const Arg& ptr10 = no_arg,
                    const Arg& ptr11 = no_arg,
                    const Arg& ptr12 = no_arg,
                    const Arg& ptr13 = no_arg,
                    const Arg& ptr14 = no_arg,
                    const Arg& ptr15 = no_arg,
                    const Arg& ptr16 = no_arg) const;

  bool Consume(StringPiece* input,
               const Arg& ptr1 = no_arg,
               const Arg& ptr2 = no_arg,
               const Arg& ptr3 = no_arg,
               const Arg& ptr4 = no_arg,
               const Arg& ptr5 = no_arg,
               const Arg& ptr6 = no_arg,
               const Arg& ptr7 = no_arg,
               const Arg& ptr8 = no_arg,
               const Arg& ptr9 = no_arg,
               const Arg& ptr10 = no_arg,
               const Arg& ptr11 = no_arg,
               const Arg& ptr12 = no_arg,
               const Arg& ptr13 = no_arg,
               const Arg& ptr14 = no_arg,
               const Arg& ptr15 = no_arg,
               const Arg& ptr16 = no_arg) const;

  bool FindAndConsume(StringPiece* input,
                      const Arg& ptr1 = no_arg,
                      const Arg& ptr2 = no_arg,
                      const Arg& ptr3 = no_arg,
                      const Arg& ptr4 = no_arg,
                      const Arg& ptr5 = no_arg,
                      const Arg& ptr6 = no_arg,
                      const Arg& ptr7 = no_arg,
                      const Arg& ptr8 = no_arg,
                      const Arg& ptr9 = no_arg,
                      const Arg& ptr10 = no_arg,
                      const Arg& ptr11 = no_arg,
                      const Arg& ptr12 = no_arg,
                      const Arg& ptr13 = no_arg,
                      const Arg& ptr14 = no_arg,
                      const Arg& ptr15 = no_arg,
                      const Arg& ptr16 = no_arg) const;

  bool Replace(const StringPiece& rewrite,
               string *str) const;

  int GlobalReplace(const StringPiece& rewrite,
                    string *str) const;

  bool Extract(const StringPiece &rewrite,
               const StringPiece &text,
               string *out) const;

  // Escapes all potentially meaningful regexp characters in
  // 'unquoted'.  The returned string, used as a regular expression,
  // will exactly match the original string.  For example,
  //           1.5-2.0?
  // may become:
  //           1\.5\-2\.0\?
  // Note QuoteMeta behaves the same as perl's QuoteMeta function,
  // *except* that it escapes the NUL character (\0) as backslash + 0,
  // rather than backslash + NUL.
  static string QuoteMeta(const StringPiece& unquoted);


  /***** Generic matching interface *****/

  // Type of match (TODO: Should be restructured as part of RE_Options)
  enum Anchor {
    UNANCHORED,         // No anchoring
    ANCHOR_START,       // Anchor at start only
    ANCHOR_BOTH         // Anchor at start and end
  };

  // General matching routine.  Stores the length of the match in
  // "*consumed" if successful.
  bool DoMatch(const StringPiece& text,
               Anchor anchor,
               int* consumed,
               const Arg* const* args, int n) const;

  // Return the number of capturing subpatterns, or -1 if the
  // regexp wasn't valid on construction.
  int NumberOfCapturingGroups() const;

  // The default value for an argument, to indicate the end of the argument
  // list. This must be used only in optional argument defaults. It should NOT
  // be passed explicitly. Some people have tried to use it like this:
  //
  //   FullMatch(x, y, &z, no_arg, &w);
  //
  // This is a mistake, and will not work.
  static Arg no_arg;

 private:

  void Init(const string& pattern, const RE_Options* options);
  void Cleanup();

  // Match against "text", filling in "vec" (up to "vecsize" * 2/3) with
  // pairs of integers for the beginning and end positions of matched
  // text.  The first pair corresponds to the entire matched text;
  // subsequent pairs correspond, in order, to parentheses-captured
  // matches.  Returns the number of pairs (one more than the number of
  // the last subpattern with a match) if matching was successful
  // and zero if the match failed.
  // I.e. for RE("(foo)|(bar)|(baz)") it will return 2, 3, and 4 when matching
  // against "foo", "bar", and "baz" respectively.
  // When matching RE("(foo)|hello") against "hello", it will return 1.
  // But the values for all subpattern are filled in into "vec".
  int TryMatch(const StringPiece& text,
               int startpos,
               Anchor anchor,
               bool empty_ok,
               int *vec,
               int vecsize) const;

  // Append the "rewrite" string, with backslash subsitutions from "text"
  // and "vec", to string "out".
  bool Rewrite(string *out,
               const StringPiece& rewrite,
               const StringPiece& text,
               int *vec,
               int veclen) const;

  // internal implementation for DoMatch
  bool DoMatchImpl(const StringPiece& text,
                   Anchor anchor,
                   int* consumed,
                   const Arg* const args[],
                   int n,
                   int* vec,
                   int vecsize) const;

  // Compile the regexp for the specified anchoring mode
  pcre* Compile(Anchor anchor);

  string        pattern_;
  RE_Options    options_;
  pcre*         re_full_;       // For full matches
  pcre*         re_partial_;    // For partial matches
  const string* error_;         // Error indicator (or points to empty string)
};

}   // namespace PCRECPP

#endif /* _PCRECPP_H */
/*autoconv-0001 C:\projects\pcre-8.31\pcrecpp.h converted to CPPH*/
/*autoconv-0013 CPPH line: 64 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 68 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 72 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 90 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 103 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 106 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 119 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 126 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 126 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 135 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 139 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 156 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 158 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 162 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 162 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 262 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 266 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 270 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 281 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 295 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 297 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 297 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 298 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 298 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 311 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 321 pcrecpp replaced by PCRECPP*/
/*autoconv-0011 CPPH line: 334 pcre.h replaced by PCRE.h*/
/*autoconv-0016 CPPH line: 334 <pcre.h> replaced by "pcre.h"/*autoconv-0013 CPPH line: 337 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 340 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 CPPH line: 708 pcrecpp replaced by PCRECPP*/
./ ADD NAME=PCREGET8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains some convenience functions for extracting substrings
from the subject string after a regex match has succeeded. The original idea
for these functions came from Scott Wimer. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*           Find number for named string         *
*************************************************/

/* This function is used by the get_first_set() function below, as well
as being generally available. It assumes that names are unique.

Arguments:
  code        the compiled regex
  stringname  the name whose number is required

Returns:      the number of the named parentheses, or a negative number
                (PCRE_ERROR_NOSUBSTRING) if not found
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_stringnumber(const pcre *code, const char *stringname)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname)
#endif
{
int rc;
int entrysize;
int top, bot;
pcre_uchar *nametable;

#ifdef COMPILE_PCRE8
if ((rc = FULLINF8(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
  return rc;
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;

if ((rc = FULLINF8(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
  return rc;
if ((rc = FULLINF8(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
  return rc;
#endif
#ifdef COMPILE_PCRE16
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
  return rc;
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;

if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
  return rc;
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
  return rc;
#endif

bot = 0;
while (top > bot)
  {
  int mid = (top + bot) / 2;
  pcre_uchar *entry = nametable + entrysize*mid;
  int c = STRCMP_UC_UC((pcre_uchar *)stringname,
    (pcre_uchar *)(entry + IMM2_SIZE));
  if (c == 0) return GET2(entry, 0);
  if (c > 0) bot = mid + 1; else top = mid;
  }

return PCRE_ERROR_NOSUBSTRING;
}



/*************************************************
*     Find (multiple) entries for named string   *
*************************************************/

/* This is used by the get_first_set() function below, as well as being
generally available. It is used when duplicated names are permitted.

Arguments:
  code        the compiled regex
  stringname  the name whose entries required
  firstptr    where to put the pointer to the first entry
  lastptr     where to put the pointer to the last entry

Returns:      the length of each entry, or a negative number
                (PCRE_ERROR_NOSUBSTRING) if not found
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_stringtable_entries(const pcre *code, const char *stringname,
  char **firstptr, char **lastptr)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
  PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr)
#endif
{
int rc;
int entrysize;
int top, bot;
pcre_uchar *nametable, *lastentry;

#ifdef COMPILE_PCRE8
if ((rc = FULLINF8(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
  return rc;
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;

if ((rc = FULLINF8(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
  return rc;
if ((rc = FULLINF8(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
  return rc;
#endif
#ifdef COMPILE_PCRE16
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
  return rc;
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;

if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
  return rc;
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
  return rc;
#endif

lastentry = nametable + entrysize * (top - 1);
bot = 0;
while (top > bot)
  {
  int mid = (top + bot) / 2;
  pcre_uchar *entry = nametable + entrysize*mid;
  int c = STRCMP_UC_UC((pcre_uchar *)stringname,
    (pcre_uchar *)(entry + IMM2_SIZE));
  if (c == 0)
    {
    pcre_uchar *first = entry;
    pcre_uchar *last = entry;
    while (first > nametable)
      {
      if (STRCMP_UC_UC((pcre_uchar *)stringname,
        (pcre_uchar *)(first - entrysize + IMM2_SIZE)) != 0) break;
      first -= entrysize;
      }
    while (last < lastentry)
      {
      if (STRCMP_UC_UC((pcre_uchar *)stringname,
        (pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break;
      last += entrysize;
      }
#ifdef COMPILE_PCRE8
    *firstptr = (char *)first;
    *lastptr = (char *)last;
#else
    *firstptr = (PCRE_UCHAR16 *)first;
    *lastptr = (PCRE_UCHAR16 *)last;
#endif
    return entrysize;
    }
  if (c > 0) bot = mid + 1; else top = mid;
  }

return PCRE_ERROR_NOSUBSTRING;
}



/*************************************************
*    Find first set of multiple named strings    *
*************************************************/

/* This function allows for duplicate names in the table of named substrings.
It returns the number of the first one that was set in a pattern match.

Arguments:
  code         the compiled regex
  stringname   the name of the capturing substring
  ovector      the vector of matched substrings

Returns:       the number of the first that is set,
               or the number of the last one if none are set,
               or a negative number on error
*/

#ifdef COMPILE_PCRE8
static int
get_first_set(const pcre *code, const char *stringname, int *ovector)
#else
static int
get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
#endif
{
const REAL_PCRE *re = (const REAL_PCRE *)code;
int entrysize;
pcre_uchar *entry;
#ifdef COMPILE_PCRE8
char *first, *last;
#else
PCRE_UCHAR16 *first, *last;
#endif

#ifdef COMPILE_PCRE8
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
  return pcre_get_stringnumber(code, stringname);
entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last);
#else
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
  return pcre16_get_stringnumber(code, stringname);
entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last);
#endif
if (entrysize <= 0) return entrysize;
for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
  {
  int n = GET2(entry, 0);
  if (ovector[n*2] >= 0) return n;
  }
return GET2(entry, 0);
}




/*************************************************
*      Copy captured string to given buffer      *
*************************************************/

/* This function copies a single captured substring into a given buffer.
Note that we use memcpy() rather than strncpy() in case there are binary zeros
in the string.

Arguments:
  subject        the subject string that was matched
  ovector        pointer to the offsets table
  stringcount    the number of substrings that were captured
                   (i.e. the yield of the PCREXEC8 call, unless
                   that was zero, in which case it should be 1/3
                   of the offset table size)
  stringnumber   the number of the required substring
  buffer         where to put the substring
  size           the size of the buffer

Returns:         if successful:
                   the length of the copied string, not including the zero
                   that is put on the end; can be zero
                 if not successful:
                   PCRE_ERROR_NOMEMORY (-6) buffer too small
                   PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_copy_substring(const char *subject, int *ovector, int stringcount,
  int stringnumber, char *buffer, int size)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
  int stringnumber, PCRE_UCHAR16 *buffer, int size)
#endif
{
int yield;
if (stringnumber < 0 || stringnumber >= stringcount)
  return PCRE_ERROR_NOSUBSTRING;
stringnumber *= 2;
yield = ovector[stringnumber+1] - ovector[stringnumber];
if (size < yield + 1) return PCRE_ERROR_NOMEMORY;
memcpy(buffer, subject + ovector[stringnumber], IN_UCHARS(yield));
buffer[yield] = 0;
return yield;
}



/*************************************************
*   Copy named captured string to given buffer   *
*************************************************/

/* This function copies a single captured substring into a given buffer,
identifying it by name. If the regex permits duplicate names, the first
substring that is set is chosen.

Arguments:
  code           the compiled regex
  subject        the subject string that was matched
  ovector        pointer to the offsets table
  stringcount    the number of substrings that were captured
                   (i.e. the yield of the PCREXEC8 call, unless
                   that was zero, in which case it should be 1/3
                   of the offset table size)
  stringname     the name of the required substring
  buffer         where to put the substring
  size           the size of the buffer

Returns:         if successful:
                   the length of the copied string, not including the zero
                   that is put on the end; can be zero
                 if not successful:
                   PCRE_ERROR_NOMEMORY (-6) buffer too small
                   PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_copy_named_substring(const pcre *code, const char *subject,
  int *ovector, int stringcount, const char *stringname,
  char *buffer, int size)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
  int *ovector, int stringcount, PCRE_SPTR16 stringname,
  PCRE_UCHAR16 *buffer, int size)
#endif
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
#ifdef COMPILE_PCRE8
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
#else
return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
#endif
}



/*************************************************
*      Copy all captured strings to new store    *
*************************************************/

/* This function gets one chunk of store and builds a list of pointers and all
of the captured substrings in it. A NULL pointer is put on the end of the list.

Arguments:
  subject        the subject string that was matched
  ovector        pointer to the offsets table
  stringcount    the number of substrings that were captured
                   (i.e. the yield of the PCREXEC8 call, unless
                   that was zero, in which case it should be 1/3
                   of the offset table size)
  listptr        set to point to the list of pointers

Returns:         if successful: 0
                 if not successful:
                   PCRE_ERROR_NOMEMORY (-6) failed to get store
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
  const char ***listptr)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
  PCRE_SPTR16 **listptr)
#endif
{
int i;
int size = sizeof(pcre_uchar *);
int double_count = stringcount * 2;
pcre_uchar **stringlist;
pcre_uchar *p;

for (i = 0; i < double_count; i += 2)
  size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1);

stringlist = (pcre_uchar **)(PUBL(malloc))(size);
if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;

#ifdef COMPILE_PCRE8
*listptr = (const char **)stringlist;
#else
*listptr = (PCRE_SPTR16 *)stringlist;
#endif
p = (pcre_uchar *)(stringlist + stringcount + 1);

for (i = 0; i < double_count; i += 2)
  {
  int len = ovector[i+1] - ovector[i];
  memcpy(p, subject + ovector[i], IN_UCHARS(len));
  *stringlist++ = p;
  p += len;
  *p++ = 0;
  }

*stringlist = NULL;
return 0;
}



/*************************************************
*   Free store obtained by get_substring_list    *
*************************************************/

/* This function exists for the benefit of people calling PCRE from non-C
programs that can call its functions, but not free() or (PUBL(free))()
directly.

Argument:   the result of a previous pcre_get_substring_list()
Returns:    nothing
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre_free_substring_list(const char **pointer)
#else
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre16_free_substring_list(PCRE_SPTR16 *pointer)
#endif
{
(PUBL(free))((void *)pointer);
}



/*************************************************
*      Copy captured string to new store         *
*************************************************/

/* This function copies a single captured substring into a piece of new
store

Arguments:
  subject        the subject string that was matched
  ovector        pointer to the offsets table
  stringcount    the number of substrings that were captured
                   (i.e. the yield of the PCREXEC8 call, unless
                   that was zero, in which case it should be 1/3
                   of the offset table size)
  stringnumber   the number of the required substring
  stringptr      where to put a pointer to the substring

Returns:         if successful:
                   the length of the string, not including the zero that
                   is put on the end; can be zero
                 if not successful:
                   PCRE_ERROR_NOMEMORY (-6) failed to get store
                   PCRE_ERROR_NOSUBSTRING (-7) substring not present
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_substring(const char *subject, int *ovector, int stringcount,
  int stringnumber, const char **stringptr)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
  int stringnumber, PCRE_SPTR16 *stringptr)
#endif
{
int yield;
pcre_uchar *substring;
if (stringnumber < 0 || stringnumber >= stringcount)
  return PCRE_ERROR_NOSUBSTRING;
stringnumber *= 2;
yield = ovector[stringnumber+1] - ovector[stringnumber];
substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1));
if (substring == NULL) return PCRE_ERROR_NOMEMORY;
memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield));
substring[yield] = 0;
#ifdef COMPILE_PCRE8
*stringptr = (const char *)substring;
#else
*stringptr = (PCRE_SPTR16)substring;
#endif
return yield;
}



/*************************************************
*   Copy named captured string to new store      *
*************************************************/

/* This function copies a single captured substring, identified by name, into
new store. If the regex permits duplicate names, the first substring that is
set is chosen.

Arguments:
  code           the compiled regex
  subject        the subject string that was matched
  ovector        pointer to the offsets table
  stringcount    the number of substrings that were captured
                   (i.e. the yield of the PCREXEC8 call, unless
                   that was zero, in which case it should be 1/3
                   of the offset table size)
  stringname     the name of the required substring
  stringptr      where to put the pointer

Returns:         if successful:
                   the length of the copied string, not including the zero
                   that is put on the end; can be zero
                 if not successful:
                   PCRE_ERROR_NOMEMORY (-6) couldn't get memory
                   PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_named_substring(const pcre *code, const char *subject,
  int *ovector, int stringcount, const char *stringname,
  const char **stringptr)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
  int *ovector, int stringcount, PCRE_SPTR16 stringname,
  PCRE_SPTR16 *stringptr)
#endif
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
#ifdef COMPILE_PCRE8
return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
#else
return pcre16_get_substring(subject, ovector, stringcount, n, stringptr);
#endif
}




/*************************************************
*       Free store obtained by get_substring     *
*************************************************/

/* This function exists for the benefit of people calling PCRE from non-C
programs that can call its functions, but not free() or (PUBL(free))()
directly.

Argument:   the result of a previous pcre_get_substring()
Returns:    nothing
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre_free_substring(const char *pointer)
#else
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre16_free_substring(PCRE_SPTR16 pointer)
#endif
{
(PUBL(free))((void *)pointer);
}

/* End of PCREGET8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_get.c converted to PCREGET8*/
/*autoconv-0010 PCREGET8 line: 47 added HAVE_CONFIG_H*/
/*autoconv-0011 PCREGET8 line: 50 config.h replaced by CONFIG.h*/
/*autoconv-0011 PCREGET8 line: 53 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 PCREGET8 line: 85 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREGET8 line: 89 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREGET8 line: 91 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREGET8 line: 154 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREGET8 line: 158 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREGET8 line: 160 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCREGET8 line: 282 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGET8 line: 333 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGET8 line: 382 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGET8 line: 472 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGET8 line: 529 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCREGET8 line: 590 pcre_get replaced by PCREGET8*/
./ ADD NAME=POSIXH 
/*************************************************
*       Perl-Compatible Regular Expressions      *
*************************************************/

#ifndef _PCREPOSIX_H
#define _PCREPOSIX_H

/* This is the header for the POSIX wrapper interface to the PCRE Perl-
Compatible Regular Expression library. It defines the things POSIX says should
be there. I hope.

            Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

/* Have to include stdlib.h in order to ensure that size_t is defined. */

#include <stdlib.h>

/* Allow for C++ users */

#ifdef __cplusplus
extern "C" {
#endif

/* Options, mostly defined by POSIX, but with some extras. */

#define REG_ICASE     0x0001   /* Maps to PCRE_CASELESS */
#define REG_NEWLINE   0x0002   /* Maps to PCRE_MULTILINE */
#define REG_NOTBOL    0x0004   /* Maps to PCRE_NOTBOL */
#define REG_NOTEOL    0x0008   /* Maps to PCRE_NOTEOL */
#define REG_DOTALL    0x0010   /* NOT defined by POSIX; maps to PCRE_DOTALL */
#define REG_NOSUB     0x0020   /* Maps to PCRE_NO_AUTO_CAPTURE */
#define REG_UTF8      0x0040   /* NOT defined by POSIX; maps to PCRE_UTF8 */
#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. */

#define REG_EXTENDED  0

/* Error values. Not all these are relevant or used by the wrapper. */

enum {
  REG_ASSERT = 1,  /* internal error ? */
  REG_BADBR,       /* invalid repeat counts in {} */
  REG_BADPAT,      /* pattern error */
  REG_BADRPT,      /* ? * + invalid */
  REG_EBRACE,      /* unbalanced {} */
  REG_EBRACK,      /* unbalanced [] */
  REG_ECOLLATE,    /* collation error - not relevant */
  REG_ECTYPE,      /* bad class */
  REG_EESCAPE,     /* bad escape sequence */
  REG_EMPTY,       /* empty expression */
  REG_EPAREN,      /* unbalanced () */
  REG_ERANGE,      /* bad range inside [] */
  REG_ESIZE,       /* expression too big */
  REG_ESPACE,      /* failed to get memory */
  REG_ESUBREG,     /* bad back reference */
  REG_INVARG,      /* bad argument */
  REG_NOMATCH      /* match failed */
};


/* The structure representing a compiled regular expression. */

typedef struct {
  void *re_pcre;
  size_t re_nsub;
  size_t re_erroffset;
} regex_t;

/* The structure in which a captured offset is returned. */

typedef int regoff_t;

typedef struct {
  regoff_t rm_so;
  regoff_t rm_eo;
} regmatch_t;

/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
export settings are needed, and are set in PCRPOSIX.c before including this
file. */

#if defined(_WIN32) && !defined(PCRE_STATIC) && !defined(PCREPOSIX_EXP_DECL)
#  define PCREPOSIX_EXP_DECL  extern __declspec(dllimport)
#  define PCREPOSIX_EXP_DEFN  __declspec(dllimport)
#endif

/* By default, we use the standard "extern" declarations. */

#ifndef PCREPOSIX_EXP_DECL
#  ifdef __cplusplus
#    define PCREPOSIX_EXP_DECL  extern "C"
#    define PCREPOSIX_EXP_DEFN  extern "C"
#  else
#    define PCREPOSIX_EXP_DECL  extern
#    define PCREPOSIX_EXP_DEFN  extern
#  endif
#endif

/* The functions */

PCREPOSIX_EXP_DECL int regcomp(regex_t *, const char *, int);
PCREPOSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t,
                     regmatch_t *, int);
PCREPOSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t);
PCREPOSIX_EXP_DECL void regfree(regex_t *);

#ifdef __cplusplus
}   /* extern "C" */
#endif

#endif /* End of PCRPOSIX.h */
/*autoconv-0001 C:\projects\pcre-8.31\pcreposix.h converted to POSIXH*/
/*autoconv-0013 POSIXH line: 114 pcreposix replaced by PCRPOSIX*/
/*autoconv-0013 POSIXH line: 146 pcreposix replaced by PCRPOSIX*/
./ ADD NAME=SCANNER8 
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sanjay Ghemawat

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <vector>
#include <assert.h>

#include "INTERNAP.h"
#include "SCANNERH.h"

using std::vector;

namespace PCRECPP {

Scanner::Scanner()
  : data_(),
    input_(data_),
    skip_(NULL),
    should_skip_(false),
    skip_repeat_(false),
    save_comments_(false),
    comments_(NULL),
    comments_offset_(0) {
}

Scanner::Scanner(const string& in)
  : data_(in),
    input_(data_),
    skip_(NULL),
    should_skip_(false),
    skip_repeat_(false),
    save_comments_(false),
    comments_(NULL),
    comments_offset_(0) {
}

Scanner::~Scanner() {
  delete skip_;
  delete comments_;
}

void Scanner::SetSkipExpression(const char* re) {
  delete skip_;
  if (re != NULL) {
    skip_ = new RE(re);
    should_skip_ = true;
    skip_repeat_ = true;
    ConsumeSkip();
  } else {
    skip_ = NULL;
    should_skip_ = false;
    skip_repeat_ = false;
  }
}

void Scanner::Skip(const char* re) {
  delete skip_;
  if (re != NULL) {
    skip_ = new RE(re);
    should_skip_ = true;
    skip_repeat_ = false;
    ConsumeSkip();
  } else {
    skip_ = NULL;
    should_skip_ = false;
    skip_repeat_ = false;
  }
}

void Scanner::DisableSkip() {
  assert(skip_ != NULL);
  should_skip_ = false;
}

void Scanner::EnableSkip() {
  assert(skip_ != NULL);
  should_skip_ = true;
  ConsumeSkip();
}

int Scanner::LineNumber() const {
  // TODO: Make it more efficient by keeping track of the last point
  // where we computed line numbers and counting newlines since then.
  // We could use std:count, but not all systems have it. :-(
  int count = 1;
  for (const char* p = data_.data(); p < input_.data(); ++p)
    if (*p == '\n')
      ++count;
  return count;
}

int Scanner::Offset() const {
  return (int)(input_.data() - data_.c_str());
}

bool Scanner::LookingAt(const RE& re) const {
  int consumed;
  return re.DoMatch(input_, RE::ANCHOR_START, &consumed, 0, 0);
}


bool Scanner::Consume(const RE& re,
                      const Arg& arg0,
                      const Arg& arg1,
                      const Arg& arg2) {
  const bool result = re.Consume(&input_, arg0, arg1, arg2);
  if (result && should_skip_) ConsumeSkip();
  return result;
}

// helper function to consume *skip_ and honour save_comments_
void Scanner::ConsumeSkip() {
  const char* start_data = input_.data();
  while (skip_->Consume(&input_)) {
    if (!skip_repeat_) {
      // Only one skip allowed.
      break;
    }
  }
  if (save_comments_) {
    if (comments_ == NULL) {
      comments_ = new vector<StringPiece>;
    }
    // already pointing one past end, so no need to +1
    int length = (int)(input_.data() - start_data);
    if (length > 0) {
      comments_->push_back(StringPiece(start_data, length));
    }
  }
}


void Scanner::GetComments(int start, int end, vector<StringPiece> *ranges) {
  // short circuit out if we've not yet initialized comments_
  // (e.g., when save_comments is false)
  if (!comments_) {
    return;
  }
  // TODO: if we guarantee that comments_ will contain StringPieces
  // that are ordered by their start, then we can do a binary search
  // for the first StringPiece at or past start and then scan for the
  // ones contained in the range, quit early (use equal_range or
  // lower_bound)
  for (vector<StringPiece>::const_iterator it = comments_->begin();
       it != comments_->end(); ++it) {
    if ((it->data() >= data_.c_str() + start &&
         it->data() + it->size() <= data_.c_str() + end)) {
      ranges->push_back(*it);
    }
  }
}


void Scanner::GetNextComments(vector<StringPiece> *ranges) {
  // short circuit out if we've not yet initialized comments_
  // (e.g., when save_comments is false)
  if (!comments_) {
    return;
  }
  for (vector<StringPiece>::const_iterator it =
         comments_->begin() + comments_offset_;
       it != comments_->end(); ++it) {
    ranges->push_back(*it);
    ++comments_offset_;
  }
}

}   // namespace PCRECPP
/*autoconv-0001 C:\projects\pcre-8.31\pcre_scanner.cc converted to SCANNER8*/
/*autoconv-0010 SCANNER8 line: 33 added HAVE_CONFIG_H*/
/*autoconv-0011 SCANNER8 line: 36 config.h replaced by CONFIG.h*/
/*autoconv-0011 SCANNER8 line: 42 pcrecpp_internal.h replaced by INTERNAP.h*/
/*autoconv-0011 SCANNER8 line: 43 pcre_scanner.h replaced by SCANNERH.h*/
/*autoconv-0013 SCANNER8 line: 47 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 SCANNER8 line: 202 pcrecpp replaced by PCRECPP*/
./ ADD NAME=UNITTESP 
// -*- coding: utf-8 -*-
//
// Copyright (c) 2005 - 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sanjay Ghemawat
//
// TODO: Test extractions for PartialMatch/Consume

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <stdio.h>
#include <string.h>      /* for memset and strcmp */
#include <cassert>
#include <vector>
#include "CPPH.h"

using PCRECPP::StringPiece;
using PCRECPP::RE;
using PCRECPP::RE_Options;
using PCRECPP::Hex;
using PCRECPP::Octal;
using PCRECPP::CRadix;

static bool VERBOSE_TEST  = false;

// CHECK dies with a fatal error if condition is not true.  It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.  Therefore, it is safe to do things like:
//    CHECK_EQ(fp->Write(x), 4)
#define CHECK(condition) do {                           \
  if (!(condition)) {                                   \
    fprintf(stderr, "%s:%d: Check failed: %s\n",        \
            __FILE__, __LINE__, #condition);            \
    exit(1);                                            \
  }                                                     \
} while (0)

#define CHECK_EQ(a, b)   CHECK(a == b)

static void Timing1(int num_iters) {
  // Same pattern lots of times
  RE pattern("ruby:\\d+");
  StringPiece p("ruby:1234");
  for (int j = num_iters; j > 0; j--) {
    CHECK(pattern.FullMatch(p));
  }
}

static void Timing2(int num_iters) {
  // Same pattern lots of times
  RE pattern("ruby:(\\d+)");
  int i;
  for (int j = num_iters; j > 0; j--) {
    CHECK(pattern.FullMatch("ruby:1234", &i));
    CHECK_EQ(i, 1234);
  }
}

static void Timing3(int num_iters) {
  string text_string;
  for (int j = num_iters; j > 0; j--) {
    text_string += "this is another line\n";
  }

  RE line_matcher(".*\n");
  string line;
  StringPiece text(text_string);
  int counter = 0;
  while (line_matcher.Consume(&text)) {
    counter++;
  }
  printf("Matched %d lines\n", counter);
}

#if 0  // uncomment this if you have a way of defining VirtualProcessSize()

static void LeakTest() {
  // Check for memory leaks
  unsigned long long initial_size = 0;
  for (int i = 0; i < 100000; i++) {
    if (i == 50000) {
      initial_size = VirtualProcessSize();
      printf("Size after 50000: %llu\n", initial_size);
    }
    char buf[100];  // definitely big enough
    sprintf(buf, "pat%09d", i);
    RE newre(buf);
  }
  uint64 final_size = VirtualProcessSize();
  printf("Size after 100000: %llu\n", final_size);
  const double growth = double(final_size - initial_size) / final_size;
  printf("Growth: %0.2f%%", growth * 100);
  CHECK(growth < 0.02);       // Allow < 2% growth
}

#endif

static void RadixTests() {
  printf("Testing hex\n");

#define CHECK_HEX(type, value) \
  do { \
    type v; \
    CHECK(RE("([0-9a-fA-F]+)[uUlL]*").FullMatch(#value, Hex(&v))); \
    CHECK_EQ(v, 0x ## value); \
    CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0x" #value, CRadix(&v))); \
    CHECK_EQ(v, 0x ## value); \
  } while(0)

  CHECK_HEX(short,              2bad);
  CHECK_HEX(unsigned short,     2badU);
  CHECK_HEX(int,                dead);
  CHECK_HEX(unsigned int,       deadU);
  CHECK_HEX(long,               7eadbeefL);
  CHECK_HEX(unsigned long,      deadbeefUL);
#ifdef HAVE_LONG_LONG
  CHECK_HEX(long long,          12345678deadbeefLL);
#endif
#ifdef HAVE_UNSIGNED_LONG_LONG
  CHECK_HEX(unsigned long long, cafebabedeadbeefULL);
#endif

#undef CHECK_HEX

  printf("Testing octal\n");

#define CHECK_OCTAL(type, value) \
  do { \
    type v; \
    CHECK(RE("([0-7]+)[uUlL]*").FullMatch(#value, Octal(&v))); \
    CHECK_EQ(v, 0 ## value); \
    CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0" #value, CRadix(&v))); \
    CHECK_EQ(v, 0 ## value); \
  } while(0)

  CHECK_OCTAL(short,              77777);
  CHECK_OCTAL(unsigned short,     177777U);
  CHECK_OCTAL(int,                17777777777);
  CHECK_OCTAL(unsigned int,       37777777777U);
  CHECK_OCTAL(long,               17777777777L);
  CHECK_OCTAL(unsigned long,      37777777777UL);
#ifdef HAVE_LONG_LONG
  CHECK_OCTAL(long long,          777777777777777777777LL);
#endif
#ifdef HAVE_UNSIGNED_LONG_LONG
  CHECK_OCTAL(unsigned long long, 1777777777777777777777ULL);
#endif

#undef CHECK_OCTAL

  printf("Testing decimal\n");

#define CHECK_DECIMAL(type, value) \
  do { \
    type v; \
    CHECK(RE("(-?[0-9]+)[uUlL]*").FullMatch(#value, &v)); \
    CHECK_EQ(v, value); \
    CHECK(RE("(-?[0-9a-fA-FxX]+)[uUlL]*").FullMatch(#value, CRadix(&v))); \
    CHECK_EQ(v, value); \
  } while(0)

  CHECK_DECIMAL(short,              -1);
  CHECK_DECIMAL(unsigned short,     9999);
  CHECK_DECIMAL(int,                -1000);
  CHECK_DECIMAL(unsigned int,       12345U);
  CHECK_DECIMAL(long,               -10000000L);
  CHECK_DECIMAL(unsigned long,      3083324652U);
#ifdef HAVE_LONG_LONG
  CHECK_DECIMAL(long long,          -100000000000000LL);
#endif
#ifdef HAVE_UNSIGNED_LONG_LONG
  CHECK_DECIMAL(unsigned long long, 1234567890987654321ULL);
#endif

#undef CHECK_DECIMAL

}

static void TestReplace() {
  printf("Testing Replace\n");

  struct ReplaceTest {
    const char *regexp;
    const char *rewrite;
    const char *original;
    const char *single;
    const char *global;
    int global_count;         // the expected return value from ReplaceAll
  };
  static const ReplaceTest tests[] = {
    { "(qu|[b-df-hj-np-tv-z]*)([a-z]+)",
      "\\2\\1ay",
      "the quick brown fox jumps over the lazy dogs.",
      "ethay quick brown fox jumps over the lazy dogs.",
      "ethay ickquay ownbray oxfay umpsjay overay ethay azylay ogsday.",
      9 },
    { "\\w+",
      "\\0-NOSPAM",
      "paul.haahr@google.com",
      "paul-NOSPAM.haahr@google.com",
      "paul-NOSPAM.haahr-NOSPAM@google-NOSPAM.com-NOSPAM",
      4 },
    { "",
      "(START)",
      "foo",
      "(START)foo",
      "(START)foo",
      1 },
    { "",
      "(START)",
      "",
      "(START)",
      "(START)",
      1 },
    { "$",
      "(END)",
      "",
      "(END)",
      "(END)",
      1 },
    { "b",
      "bb",
      "ababababab",
      "abbabababab",
      "abbabbabbabbabb",
       5 },
    { "b",
      "bb",
      "bbbbbb",
      "bbbbbbb",
      "bbbbbbbbbbbb",
      6 },
    { "b+",
      "bb",
      "bbbbbb",
      "bb",
      "bb",
      1 },
    { "b*",
      "bb",
      "bbbbbb",
      "bb",
      "bbbb",
      2 },
    { "b*",
      "bb",
      "aaaaa",
      "bbaaaaa",
      "bbabbabbabbabbabb",
      6 },
    { "b*",
      "bb",
      "aa\naa\n",
      "bbaa\naa\n",
      "bbabbabb\nbbabbabb\nbb",
      7 },
    { "b*",
      "bb",
      "aa\raa\r",
      "bbaa\raa\r",
      "bbabbabb\rbbabbabb\rbb",
      7 },
    { "b*",
      "bb",
      "aa\r\naa\r\n",
      "bbaa\r\naa\r\n",
      "bbabbabb\r\nbbabbabb\r\nbb",
      7 },
    // Check empty-string matching (it's tricky!)
    { "aa|b*",
      "@",
      "aa",
      "@",
      "@@",
      2 },
    { "b*|aa",
      "@",
      "aa",
      "@aa",
      "@@@",
      3 },
#ifdef SUPPORT_UTF8
    { "b*",
      "bb",
      "\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\xB8",   // utf8
      "bb\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\xB8",
      "bb\xE3\x83\x9B""bb""\xE3\x83\xBC""bb""\xE3\x83\xA0""bb""\xE3\x81\xB8""bb",
      5 },
    { "b*",
      "bb",
      "\xE3\x83\x9B\r\n\xE3\x83\xBC\r\xE3\x83\xA0\n\xE3\x81\xB8\r\n",   // utf8
      "bb\xE3\x83\x9B\r\n\xE3\x83\xBC\r\xE3\x83\xA0\n\xE3\x81\xB8\r\n",
      ("bb\xE3\x83\x9B""bb\r\nbb""\xE3\x83\xBC""bb\rbb""\xE3\x83\xA0"
       "bb\nbb""\xE3\x81\xB8""bb\r\nbb"),
      9 },
#endif
    { "", NULL, NULL, NULL, NULL, 0 }
  };

#ifdef SUPPORT_UTF8
  const bool support_utf8 = true;
#else
  const bool support_utf8 = false;
#endif

  for (const ReplaceTest *t = tests; t->original != NULL; ++t) {
    RE re(t->regexp, RE_Options(PCRE_NEWLINE_CRLF).set_utf8(support_utf8));
    assert(re.error().empty());
    string one(t->original);
    CHECK(re.Replace(t->rewrite, &one));
    CHECK_EQ(one, t->single);
    string all(t->original);
    const int replace_count = re.GlobalReplace(t->rewrite, &all);
    CHECK_EQ(all, t->global);
    CHECK_EQ(replace_count, t->global_count);
  }

  // One final test: test \r\n replacement when we're not in CRLF mode
  {
    RE re("b*", RE_Options(PCRE_NEWLINE_CR).set_utf8(support_utf8));
    assert(re.error().empty());
    string all("aa\r\naa\r\n");
    CHECK_EQ(re.GlobalReplace("bb", &all), 9);
    CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb"));
  }
  {
    RE re("b*", RE_Options(PCRE_NEWLINE_LF).set_utf8(support_utf8));
    assert(re.error().empty());
    string all("aa\r\naa\r\n");
    CHECK_EQ(re.GlobalReplace("bb", &all), 9);
    CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb"));
  }
  // TODO: test what happens when no PCRE_NEWLINE_* flag is set.
  //       Alas, the answer depends on how pcre was compiled.
}

static void TestExtract() {
  printf("Testing Extract\n");

  string s;

  CHECK(RE("(.*)@([.]*)").Extract("\\2!\\1", "boris@kremvax.ru", &s));
  CHECK_EQ(s, "kremvax!boris");

  // check the RE interface as well
  CHECK(RE(".*").Extract("'\\0'", "foo", &s));
  CHECK_EQ(s, "'foo'");
  CHECK(!RE("bar").Extract("'\\0'", "baz", &s));
  CHECK_EQ(s, "'foo'");
}

static void TestConsume() {
  printf("Testing Consume\n");

  string word;

  string s("   aaa b!@#$@#$cccc");
  StringPiece input(s);

  RE r("\\s*(\\w+)");    // matches a word, possibly proceeded by whitespace
  CHECK(r.Consume(&input, &word));
  CHECK_EQ(word, "aaa");
  CHECK(r.Consume(&input, &word));
  CHECK_EQ(word, "b");
  CHECK(! r.Consume(&input, &word));
}

static void TestFindAndConsume() {
  printf("Testing FindAndConsume\n");

  string word;

  string s("   aaa b!@#$@#$cccc");
  StringPiece input(s);

  RE r("(\\w+)");      // matches a word
  CHECK(r.FindAndConsume(&input, &word));
  CHECK_EQ(word, "aaa");
  CHECK(r.FindAndConsume(&input, &word));
  CHECK_EQ(word, "b");
  CHECK(r.FindAndConsume(&input, &word));
  CHECK_EQ(word, "cccc");
  CHECK(! r.FindAndConsume(&input, &word));
}

static void TestMatchNumberPeculiarity() {
  printf("Testing match-number peculiarity\n");

  string word1;
  string word2;
  string word3;

  RE r("(foo)|(bar)|(baz)");
  CHECK(r.PartialMatch("foo", &word1, &word2, &word3));
  CHECK_EQ(word1, "foo");
  CHECK_EQ(word2, "");
  CHECK_EQ(word3, "");
  CHECK(r.PartialMatch("bar", &word1, &word2, &word3));
  CHECK_EQ(word1, "");
  CHECK_EQ(word2, "bar");
  CHECK_EQ(word3, "");
  CHECK(r.PartialMatch("baz", &word1, &word2, &word3));
  CHECK_EQ(word1, "");
  CHECK_EQ(word2, "");
  CHECK_EQ(word3, "baz");
  CHECK(!r.PartialMatch("f", &word1, &word2, &word3));

  string a;
  CHECK(RE("(foo)|hello").FullMatch("hello", &a));
  CHECK_EQ(a, "");
}

static void TestRecursion() {
  printf("Testing recursion\n");

  // Get one string that passes (sometimes), one that never does.
  string text_good("abcdefghijk");
  string text_bad("acdefghijkl");

  // According to PCRETEST, matching text_good against (\w+)*b
  // requires match_limit of at least 8192, and match_recursion_limit
  // of at least 37.

  RE_Options options_ml;
  options_ml.set_match_limit(8192);
  RE re("(\\w+)*b", options_ml);
  CHECK(re.PartialMatch(text_good) == true);
  CHECK(re.PartialMatch(text_bad) == false);
  CHECK(re.FullMatch(text_good) == false);
  CHECK(re.FullMatch(text_bad) == false);

  options_ml.set_match_limit(1024);
  RE re2("(\\w+)*b", options_ml);
  CHECK(re2.PartialMatch(text_good) == false);   // because of match_limit
  CHECK(re2.PartialMatch(text_bad) == false);
  CHECK(re2.FullMatch(text_good) == false);
  CHECK(re2.FullMatch(text_bad) == false);

  RE_Options options_mlr;
  options_mlr.set_match_limit_recursion(50);
  RE re3("(\\w+)*b", options_mlr);
  CHECK(re3.PartialMatch(text_good) == true);
  CHECK(re3.PartialMatch(text_bad) == false);
  CHECK(re3.FullMatch(text_good) == false);
  CHECK(re3.FullMatch(text_bad) == false);

  options_mlr.set_match_limit_recursion(10);
  RE re4("(\\w+)*b", options_mlr);
  CHECK(re4.PartialMatch(text_good) == false);
  CHECK(re4.PartialMatch(text_bad) == false);
  CHECK(re4.FullMatch(text_good) == false);
  CHECK(re4.FullMatch(text_bad) == false);
}

// A meta-quoted string, interpreted as a pattern, should always match
// the original unquoted string.
static void TestQuoteMeta(string unquoted, RE_Options options = RE_Options()) {
  string quoted = RE::QuoteMeta(unquoted);
  RE re(quoted, options);
  CHECK(re.FullMatch(unquoted));
}

// A string containing meaningful regexp characters, which is then meta-
// quoted, should not generally match a string the unquoted string does.
static void NegativeTestQuoteMeta(string unquoted, string should_not_match,
                                  RE_Options options = RE_Options()) {
  string quoted = RE::QuoteMeta(unquoted);
  RE re(quoted, options);
  CHECK(!re.FullMatch(should_not_match));
}

// Tests that quoted meta characters match their original strings,
// and that a few things that shouldn't match indeed do not.
static void TestQuotaMetaSimple() {
  TestQuoteMeta("foo");
  TestQuoteMeta("foo.bar");
  TestQuoteMeta("foo\\.bar");
  TestQuoteMeta("[1-9]");
  TestQuoteMeta("1.5-2.0?");
  TestQuoteMeta("\\d");
  TestQuoteMeta("Who doesn't like ice cream?");
  TestQuoteMeta("((a|b)c?d*e+[f-h]i)");
  TestQuoteMeta("((?!)xxx).*yyy");
  TestQuoteMeta("([");
  TestQuoteMeta(string("foo\0bar", 7));
}

static void TestQuoteMetaSimpleNegative() {
  NegativeTestQuoteMeta("foo", "bar");
  NegativeTestQuoteMeta("...", "bar");
  NegativeTestQuoteMeta("\\.", ".");
  NegativeTestQuoteMeta("\\.", "..");
  NegativeTestQuoteMeta("(a)", "a");
  NegativeTestQuoteMeta("(a|b)", "a");
  NegativeTestQuoteMeta("(a|b)", "(a)");
  NegativeTestQuoteMeta("(a|b)", "a|b");
  NegativeTestQuoteMeta("[0-9]", "0");
  NegativeTestQuoteMeta("[0-9]", "0-9");
  NegativeTestQuoteMeta("[0-9]", "[9]");
  NegativeTestQuoteMeta("((?!)xxx)", "xxx");
}

static void TestQuoteMetaLatin1() {
  TestQuoteMeta("3\xb2 = 9");
}

static void TestQuoteMetaUtf8() {
#ifdef SUPPORT_UTF8
  TestQuoteMeta("Pl\xc3\xa1\x63ido Domingo", PCRECPP::UTF8());
  TestQuoteMeta("xyz", PCRECPP::UTF8());            // No fancy utf8
  TestQuoteMeta("\xc2\xb0", PCRECPP::UTF8());       // 2-byte utf8 (degree symbol)
  TestQuoteMeta("27\xc2\xb0 degrees", PCRECPP::UTF8());  // As a middle character
  TestQuoteMeta("\xe2\x80\xb3", PCRECPP::UTF8());   // 3-byte utf8 (double prime)
  TestQuoteMeta("\xf0\x9d\x85\x9f", PCRECPP::UTF8()); // 4-byte utf8 (music note)
  TestQuoteMeta("27\xc2\xb0"); // Interpreted as Latin-1, but should still work
  NegativeTestQuoteMeta("27\xc2\xb0",               // 2-byte utf (degree symbol)
                        "27\\\xc2\\\xb0",
                        PCRECPP::UTF8());
#endif
}

static void TestQuoteMetaAll() {
  printf("Testing QuoteMeta\n");
  TestQuotaMetaSimple();
  TestQuoteMetaSimpleNegative();
  TestQuoteMetaLatin1();
  TestQuoteMetaUtf8();
}

//
// Options tests contributed by
// Giuseppe Maxia, CTO, Stardata s.r.l.
// July 2005
//
static void GetOneOptionResult(
                const char *option_name,
                const char *regex,
                const char *str,
                RE_Options options,
                bool full,
                string expected) {

  printf("Testing Option <%s>\n", option_name);
  if(VERBOSE_TEST)
    printf("/%s/ finds \"%s\" within \"%s\" \n",
                    regex,
                    expected.c_str(),
                    str);
  string captured("");
  if (full)
    RE(regex,options).FullMatch(str, &captured);
  else
    RE(regex,options).PartialMatch(str, &captured);
  CHECK_EQ(captured, expected);
}

static void TestOneOption(
                const char *option_name,
                const char *regex,
                const char *str,
                RE_Options options,
                bool full,
                bool assertive = true) {

  printf("Testing Option <%s>\n", option_name);
  if (VERBOSE_TEST)
    printf("'%s' %s /%s/ \n",
                  str,
                  (assertive? "matches" : "doesn't match"),
                  regex);
  if (assertive) {
    if (full)
      CHECK(RE(regex,options).FullMatch(str));
    else
      CHECK(RE(regex,options).PartialMatch(str));
  } else {
    if (full)
      CHECK(!RE(regex,options).FullMatch(str));
    else
      CHECK(!RE(regex,options).PartialMatch(str));
  }
}

static void Test_CASELESS() {
  RE_Options options;
  RE_Options options2;

  options.set_caseless(true);
  TestOneOption("CASELESS (class)",  "HELLO",    "hello", options, false);
  TestOneOption("CASELESS (class2)", "HELLO",    "hello", options2.set_caseless(true), false);
  TestOneOption("CASELESS (class)",  "[A-Z]+$", "Hello", options, false);

  TestOneOption("CASELESS (function)", "HELLO",    "hello", PCRECPP::CASELESS(), false);
  TestOneOption("CASELESS (function)", "[A-Z]+$", "Hello", PCRECPP::CASELESS(), false);
  options.set_caseless(false);
  TestOneOption("no CASELESS", "HELLO",    "hello", options, false, false);
}

static void Test_MULTILINE() {
  RE_Options options;
  RE_Options options2;
  const char *str = "HELLO\n" "cruel\n" "world\n";

  options.set_multiline(true);
  TestOneOption("MULTILINE (class)",    "cruel$", str, options, false);
  TestOneOption("MULTILINE (class2)",   "cruel$", str, options2.set_multiline(true), false);
  TestOneOption("MULTILINE (function)", "cruel$", str, PCRECPP::MULTILINE(), false);
  options.set_multiline(false);
  TestOneOption("no MULTILINE", "cruel$", str, options, false, false);
}

static void Test_DOTALL() {
  RE_Options options;
  RE_Options options2;
  const char *str = "HELLO\n" "cruel\n" "world";

  options.set_dotall(true);
  TestOneOption("DOTALL (class)",    "HELLO.*world", str, options, true);
  TestOneOption("DOTALL (class2)",   "HELLO.*world", str, options2.set_dotall(true), true);
  TestOneOption("DOTALL (function)",    "HELLO.*world", str, PCRECPP::DOTALL(), true);
  options.set_dotall(false);
  TestOneOption("no DOTALL", "HELLO.*world", str, options, true, false);
}

static void Test_DOLLAR_ENDONLY() {
  RE_Options options;
  RE_Options options2;
  const char *str = "HELLO world\n";

  TestOneOption("no DOLLAR_ENDONLY", "world$", str, options, false);
  options.set_dollar_endonly(true);
  TestOneOption("DOLLAR_ENDONLY 1",    "world$", str, options, false, false);
  TestOneOption("DOLLAR_ENDONLY 2",    "world$", str, options2.set_dollar_endonly(true), false, false);
}

static void Test_EXTRA() {
  RE_Options options;
  const char *str = "HELLO";

  options.set_extra(true);
  TestOneOption("EXTRA 1", "\\HELL\\O", str, options, true, false );
  TestOneOption("EXTRA 2", "\\HELL\\O", str, RE_Options().set_extra(true), true, false );
  options.set_extra(false);
  TestOneOption("no EXTRA", "\\HELL\\O", str, options, true );
}

static void Test_EXTENDED() {
  RE_Options options;
  RE_Options options2;
  const char *str = "HELLO world";

  options.set_extended(true);
  TestOneOption("EXTENDED (class)",    "HELLO world", str, options, false, false);
  TestOneOption("EXTENDED (class2)",   "HELLO world", str, options2.set_extended(true), false, false);
  TestOneOption("EXTENDED (class)",
                    " HE L{2} O "
                    "\\s+        "
                    "\\w+ $      ",
                    str,
                    options,
                    false);

  TestOneOption("EXTENDED (function)",    "HELLO world", str, PCRECPP::EXTENDED(), false, false);
  TestOneOption("EXTENDED (function)",
                    " HE L{2} O "
                    "\\s+        "
                    "\\w+ $      ",
                    str,
                    PCRECPP::EXTENDED(),
                    false);

  options.set_extended(false);
  TestOneOption("no EXTENDED", "HELLO world", str, options, false);
}

static void Test_NO_AUTO_CAPTURE() {
  RE_Options options;
  const char *str = "HELLO world";
  string captured;

  printf("Testing Option <no NO_AUTO_CAPTURE>\n");
  if (VERBOSE_TEST)
    printf("parentheses capture text\n");
  RE re("(world|universe)$", options);
  CHECK(re.Extract("\\1", str , &captured));
  CHECK_EQ(captured, "world");
  options.set_no_auto_capture(true);
  printf("testing Option <NO_AUTO_CAPTURE>\n");
  if (VERBOSE_TEST)
    printf("parentheses do not capture text\n");
  re.Extract("\\1",str, &captured );
  CHECK_EQ(captured, "world");
}

static void Test_UNGREEDY() {
  RE_Options options;
  const char *str = "HELLO, 'this' is the 'world'";

  options.set_ungreedy(true);
  GetOneOptionResult("UNGREEDY 1", "('.*')", str, options, false, "'this'" );
  GetOneOptionResult("UNGREEDY 2", "('.*')", str, RE_Options().set_ungreedy(true), false, "'this'" );
  GetOneOptionResult("UNGREEDY", "('.*?')", str, options, false, "'this' is the 'world'" );

  options.set_ungreedy(false);
  GetOneOptionResult("no UNGREEDY", "('.*')", str, options, false, "'this' is the 'world'" );
  GetOneOptionResult("no UNGREEDY", "('.*?')", str, options, false, "'this'" );
}

static void Test_all_options() {
  const char *str = "HELLO\n" "cruel\n" "world";
  RE_Options options;
  options.set_all_options(PCRE_CASELESS | PCRE_DOTALL);

  TestOneOption("all_options (CASELESS|DOTALL)", "hello.*WORLD", str , options, false);
  options.set_all_options(0);
  TestOneOption("all_options (0)", "hello.*WORLD", str , options, false, false);
  options.set_all_options(PCRE_MULTILINE | PCRE_EXTENDED);

  TestOneOption("all_options (MULTILINE|EXTENDED)", "  c r u e l $ ", str, options, false);
  TestOneOption("all_options (MULTILINE|EXTENDED) with constructor",
                  "  c r u e l $ ",
                  str,
                  RE_Options(PCRE_MULTILINE | PCRE_EXTENDED),
                  false);

  TestOneOption("all_options (MULTILINE|EXTENDED) with concatenation",
                  "  c r u e l $ ",
                  str,
                  RE_Options()
                       .set_multiline(true)
                       .set_extended(true),
                  false);

  options.set_all_options(0);
  TestOneOption("all_options (0)", " c r u e l $", str, options, false, false);

}

static void TestOptions() {
  printf("Testing Options\n");
  Test_CASELESS();
  Test_MULTILINE();
  Test_DOTALL();
  Test_DOLLAR_ENDONLY();
  Test_EXTENDED();
  Test_NO_AUTO_CAPTURE();
  Test_UNGREEDY();
  Test_EXTRA();
  Test_all_options();
}

static void TestConstructors() {
  printf("Testing constructors\n");

  RE_Options options;
  options.set_dotall(true);
  const char *str = "HELLO\n" "cruel\n" "world";

  RE orig("HELLO.*world", options);
  CHECK(orig.FullMatch(str));

  RE copy1(orig);
  CHECK(copy1.FullMatch(str));

  RE copy2("not a match");
  CHECK(!copy2.FullMatch(str));
  copy2 = copy1;
  CHECK(copy2.FullMatch(str));
  copy2 = orig;
  CHECK(copy2.FullMatch(str));

  // Make sure when we assign to ourselves, nothing bad happens
  orig = orig;
  copy1 = copy1;
  copy2 = copy2;
  CHECK(orig.FullMatch(str));
  CHECK(copy1.FullMatch(str));
  CHECK(copy2.FullMatch(str));
}

int main(int argc, char** argv) {
  // Treat any flag as --help
  if (argc > 1 && argv[1][0] == '-') {
    printf("Usage: %s [timing1|timing2|timing3 num-iters]\n"
           "       If 'timingX ###' is specified, run the given timing test\n"
           "       with the given number of iterations, rather than running\n"
           "       the default corectness test.\n", argv[0]);
    return 0;
  }

  if (argc > 1) {
    if ( argc == 2 || atoi(argv[2]) == 0) {
      printf("timing mode needs a num-iters argument\n");
      return 1;
    }
    if (!strcmp(argv[1], "timing1"))
      Timing1(atoi(argv[2]));
    else if (!strcmp(argv[1], "timing2"))
      Timing2(atoi(argv[2]));
    else if (!strcmp(argv[1], "timing3"))
      Timing3(atoi(argv[2]));
    else
      printf("Unknown argument '%s'\n", argv[1]);
    return 0;
  }

  printf("PCRE C++ wrapper tests\n");
  printf("Testing FullMatch\n");

  int i;
  string s;

  /***** FullMatch with no args *****/

  CHECK(RE("h.*o").FullMatch("hello"));
  CHECK(!RE("h.*o").FullMatch("othello"));     // Must be anchored at front
  CHECK(!RE("h.*o").FullMatch("hello!"));      // Must be anchored at end
  CHECK(RE("a*").FullMatch("aaaa"));           // Fullmatch with normal op
  CHECK(RE("a*?").FullMatch("aaaa"));          // Fullmatch with nongreedy op
  CHECK(RE("a*?\\z").FullMatch("aaaa"));       // Two unusual ops

  /***** FullMatch with args *****/

  // Zero-arg
  CHECK(RE("\\d+").FullMatch("1001"));

  // Single-arg
  CHECK(RE("(\\d+)").FullMatch("1001",   &i));
  CHECK_EQ(i, 1001);
  CHECK(RE("(-?\\d+)").FullMatch("-123", &i));
  CHECK_EQ(i, -123);
  CHECK(!RE("()\\d+").FullMatch("10", &i));
  CHECK(!RE("(\\d+)").FullMatch("1234567890123456789012345678901234567890",
                                &i));

  // Digits surrounding integer-arg
  CHECK(RE("1(\\d*)4").FullMatch("1234", &i));
  CHECK_EQ(i, 23);
  CHECK(RE("(\\d)\\d+").FullMatch("1234", &i));
  CHECK_EQ(i, 1);
  CHECK(RE("(-\\d)\\d+").FullMatch("-1234", &i));
  CHECK_EQ(i, -1);
  CHECK(RE("(\\d)").PartialMatch("1234", &i));
  CHECK_EQ(i, 1);
  CHECK(RE("(-\\d)").PartialMatch("-1234", &i));
  CHECK_EQ(i, -1);

  // String-arg
  CHECK(RE("h(.*)o").FullMatch("hello", &s));
  CHECK_EQ(s, string("ell"));

  // StringPiece-arg
  StringPiece sp;
  CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &sp, &i));
  CHECK_EQ(sp.size(), 4);
  CHECK(memcmp(sp.data(), "ruby", 4) == 0);
  CHECK_EQ(i, 1234);

  // Multi-arg
  CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &s, &i));
  CHECK_EQ(s, string("ruby"));
  CHECK_EQ(i, 1234);

  // Ignore non-void* NULL arg
  CHECK(RE("he(.*)lo").FullMatch("hello", (char*)NULL));
  CHECK(RE("h(.*)o").FullMatch("hello", (string*)NULL));
  CHECK(RE("h(.*)o").FullMatch("hello", (StringPiece*)NULL));
  CHECK(RE("(.*)").FullMatch("1234", (int*)NULL));
#ifdef HAVE_LONG_LONG
  CHECK(RE("(.*)").FullMatch("1234567890123456", (long long*)NULL));
#endif
  CHECK(RE("(.*)").FullMatch("123.4567890123456", (double*)NULL));
  CHECK(RE("(.*)").FullMatch("123.4567890123456", (float*)NULL));

  // Fail on non-void* NULL arg if the match doesn't parse for the given type.
  CHECK(!RE("h(.*)lo").FullMatch("hello", &s, (char*)NULL));
  CHECK(!RE("(.*)").FullMatch("hello", (int*)NULL));
  CHECK(!RE("(.*)").FullMatch("1234567890123456", (int*)NULL));
  CHECK(!RE("(.*)").FullMatch("hello", (double*)NULL));
  CHECK(!RE("(.*)").FullMatch("hello", (float*)NULL));

  // Ignored arg
  CHECK(RE("(\\w+)(:)(\\d+)").FullMatch("ruby:1234", &s, (void*)NULL, &i));
  CHECK_EQ(s, string("ruby"));
  CHECK_EQ(i, 1234);

  // Type tests
  {
    char c;
    CHECK(RE("(H)ello").FullMatch("Hello", &c));
    CHECK_EQ(c, 'H');
  }
  {
    unsigned char c;
    CHECK(RE("(H)ello").FullMatch("Hello", &c));
    CHECK_EQ(c, static_cast<unsigned char>('H'));
  }
  {
    short v;
    CHECK(RE("(-?\\d+)").FullMatch("100",     &v));    CHECK_EQ(v, 100);
    CHECK(RE("(-?\\d+)").FullMatch("-100",    &v));    CHECK_EQ(v, -100);
    CHECK(RE("(-?\\d+)").FullMatch("32767",   &v));    CHECK_EQ(v, 32767);
    CHECK(RE("(-?\\d+)").FullMatch("-32768",  &v));    CHECK_EQ(v, -32768);
    CHECK(!RE("(-?\\d+)").FullMatch("-32769", &v));
    CHECK(!RE("(-?\\d+)").FullMatch("32768",  &v));
  }
  {
    unsigned short v;
    CHECK(RE("(\\d+)").FullMatch("100",     &v));    CHECK_EQ(v, 100);
    CHECK(RE("(\\d+)").FullMatch("32767",   &v));    CHECK_EQ(v, 32767);
    CHECK(RE("(\\d+)").FullMatch("65535",   &v));    CHECK_EQ(v, 65535);
    CHECK(!RE("(\\d+)").FullMatch("65536",  &v));
  }
  {
    int v;
    static const int max_value = 0x7fffffff;
    static const int min_value = -max_value - 1;
    CHECK(RE("(-?\\d+)").FullMatch("100",         &v)); CHECK_EQ(v, 100);
    CHECK(RE("(-?\\d+)").FullMatch("-100",        &v)); CHECK_EQ(v, -100);
    CHECK(RE("(-?\\d+)").FullMatch("2147483647",  &v)); CHECK_EQ(v, max_value);
    CHECK(RE("(-?\\d+)").FullMatch("-2147483648", &v)); CHECK_EQ(v, min_value);
    CHECK(!RE("(-?\\d+)").FullMatch("-2147483649", &v));
    CHECK(!RE("(-?\\d+)").FullMatch("2147483648",  &v));
  }
  {
    unsigned int v;
    static const unsigned int max_value = 0xfffffffful;
    CHECK(RE("(\\d+)").FullMatch("100",         &v)); CHECK_EQ(v, 100);
    CHECK(RE("(\\d+)").FullMatch("4294967295",  &v)); CHECK_EQ(v, max_value);
    CHECK(!RE("(\\d+)").FullMatch("4294967296", &v));
  }
#ifdef HAVE_LONG_LONG
# if defined(__MINGW__) || defined(__MINGW32__)
#   define LLD "%I64d"
#   define LLU "%I64u"
# else
#   define LLD "%lld"
#   define LLU "%llu"
# endif
  {
    long long v;
    static const long long max_value = 0x7fffffffffffffffLL;
    static const long long min_value = -max_value - 1;
    char buf[32];  // definitely big enough for a long long

    CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100);
    CHECK(RE("(-?\\d+)").FullMatch("-100",&v)); CHECK_EQ(v, -100);

    sprintf(buf, LLD, max_value);
    CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value);

    sprintf(buf, LLD, min_value);
    CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, min_value);

    sprintf(buf, LLD, max_value);
    assert(buf[strlen(buf)-1] != '9');
    buf[strlen(buf)-1]++;
    CHECK(!RE("(-?\\d+)").FullMatch(buf, &v));

    sprintf(buf, LLD, min_value);
    assert(buf[strlen(buf)-1] != '9');
    buf[strlen(buf)-1]++;
    CHECK(!RE("(-?\\d+)").FullMatch(buf, &v));
  }
#endif
#if defined HAVE_UNSIGNED_LONG_LONG && defined HAVE_LONG_LONG
  {
    unsigned long long v;
    long long v2;
    static const unsigned long long max_value = 0xffffffffffffffffULL;
    char buf[32];  // definitely big enough for a unsigned long long

    CHECK(RE("(-?\\d+)").FullMatch("100",&v)); CHECK_EQ(v, 100);
    CHECK(RE("(-?\\d+)").FullMatch("-100",&v2)); CHECK_EQ(v2, -100);

    sprintf(buf, LLU, max_value);
    CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value);

    assert(buf[strlen(buf)-1] != '9');
    buf[strlen(buf)-1]++;
    CHECK(!RE("(-?\\d+)").FullMatch(buf, &v));
  }
#endif
  {
    float v;
    CHECK(RE("(.*)").FullMatch("100", &v));
    CHECK(RE("(.*)").FullMatch("-100.", &v));
    CHECK(RE("(.*)").FullMatch("1e23", &v));
  }
  {
    double v;
    CHECK(RE("(.*)").FullMatch("100", &v));
    CHECK(RE("(.*)").FullMatch("-100.", &v));
    CHECK(RE("(.*)").FullMatch("1e23", &v));
  }

  // Check that matching is fully anchored
  CHECK(!RE("(\\d+)").FullMatch("x1001",  &i));
  CHECK(!RE("(\\d+)").FullMatch("1001x",  &i));
  CHECK(RE("x(\\d+)").FullMatch("x1001", &i)); CHECK_EQ(i, 1001);
  CHECK(RE("(\\d+)x").FullMatch("1001x", &i)); CHECK_EQ(i, 1001);

  // Braces
  CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcd"));
  CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcde"));
  CHECK(!RE("[0-9a-f+.-]{5,}").FullMatch("0abc"));

  // Complicated RE
  CHECK(RE("foo|bar|[A-Z]").FullMatch("foo"));
  CHECK(RE("foo|bar|[A-Z]").FullMatch("bar"));
  CHECK(RE("foo|bar|[A-Z]").FullMatch("X"));
  CHECK(!RE("foo|bar|[A-Z]").FullMatch("XY"));

  // Check full-match handling (needs '$' tacked on internally)
  CHECK(RE("fo|foo").FullMatch("fo"));
  CHECK(RE("fo|foo").FullMatch("foo"));
  CHECK(RE("fo|foo$").FullMatch("fo"));
  CHECK(RE("fo|foo$").FullMatch("foo"));
  CHECK(RE("foo$").FullMatch("foo"));
  CHECK(!RE("foo\\$").FullMatch("foo$bar"));
  CHECK(!RE("fo|bar").FullMatch("fox"));

  // Uncomment the following if we change the handling of '$' to
  // prevent it from matching a trailing newline
  if (false) {
    // Check that we don't get bitten by pcre's special handling of a
    // '\n' at the end of the string matching '$'
    CHECK(!RE("foo$").PartialMatch("foo\n"));
  }

  // Number of args
  int a[16];
  CHECK(RE("").FullMatch(""));

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d){1}").FullMatch("1",
                                 &a[0]));
  CHECK_EQ(a[0], 1);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)").FullMatch("12",
                                   &a[0],  &a[1]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)(\\d)").FullMatch("123",
                                        &a[0],  &a[1],  &a[2]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);
  CHECK_EQ(a[2], 3);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)(\\d)(\\d)").FullMatch("1234",
                                             &a[0],  &a[1],  &a[2],  &a[3]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);
  CHECK_EQ(a[2], 3);
  CHECK_EQ(a[3], 4);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("12345",
                                                  &a[0],  &a[1],  &a[2],
                                                  &a[3],  &a[4]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);
  CHECK_EQ(a[2], 3);
  CHECK_EQ(a[3], 4);
  CHECK_EQ(a[4], 5);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("123456",
                                                       &a[0],  &a[1],  &a[2],
                                                       &a[3],  &a[4],  &a[5]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);
  CHECK_EQ(a[2], 3);
  CHECK_EQ(a[3], 4);
  CHECK_EQ(a[4], 5);
  CHECK_EQ(a[5], 6);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("1234567",
                                                            &a[0],  &a[1],  &a[2],  &a[3],
                                                            &a[4],  &a[5],  &a[6]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);
  CHECK_EQ(a[2], 3);
  CHECK_EQ(a[3], 4);
  CHECK_EQ(a[4], 5);
  CHECK_EQ(a[5], 6);
  CHECK_EQ(a[6], 7);

  memset(a, 0, sizeof(0));
  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)"
           "(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch(
               "1234567890123456",
               &a[0],  &a[1],  &a[2],  &a[3],
               &a[4],  &a[5],  &a[6],  &a[7],
               &a[8],  &a[9],  &a[10], &a[11],
               &a[12], &a[13], &a[14], &a[15]));
  CHECK_EQ(a[0], 1);
  CHECK_EQ(a[1], 2);
  CHECK_EQ(a[2], 3);
  CHECK_EQ(a[3], 4);
  CHECK_EQ(a[4], 5);
  CHECK_EQ(a[5], 6);
  CHECK_EQ(a[6], 7);
  CHECK_EQ(a[7], 8);
  CHECK_EQ(a[8], 9);
  CHECK_EQ(a[9], 0);
  CHECK_EQ(a[10], 1);
  CHECK_EQ(a[11], 2);
  CHECK_EQ(a[12], 3);
  CHECK_EQ(a[13], 4);
  CHECK_EQ(a[14], 5);
  CHECK_EQ(a[15], 6);

  /***** PartialMatch *****/

  printf("Testing PartialMatch\n");

  CHECK(RE("h.*o").PartialMatch("hello"));
  CHECK(RE("h.*o").PartialMatch("othello"));
  CHECK(RE("h.*o").PartialMatch("hello!"));
  CHECK(RE("((((((((((((((((((((x))))))))))))))))))))").PartialMatch("x"));

  /***** other tests *****/

  RadixTests();
  TestReplace();
  TestExtract();
  TestConsume();
  TestFindAndConsume();
  TestQuoteMetaAll();
  TestMatchNumberPeculiarity();

  // Check the pattern() accessor
  {
    const string kPattern = "http://([/]+)/.*";
    const RE re(kPattern);
    CHECK_EQ(kPattern, re.pattern());
  }

  // Check RE error field.
  {
    RE re("foo");
    CHECK(re.error().empty());  // Must have no error
  }

#ifdef SUPPORT_UTF8
  // Check UTF-8 handling
  {
    printf("Testing UTF-8 handling\n");

    // Three Japanese characters (nihongo)
    const unsigned char utf8_string[] = {
         0xe6, 0x97, 0xa5, // 65e5
         0xe6, 0x9c, 0xac, // 627c
         0xe8, 0xaa, 0x9e, // 8a9e
         0
    };
    const unsigned char utf8_pattern[] = {
         '.',
         0xe6, 0x9c, 0xac, // 627c
         '.',
         0
    };

    // Both should match in either mode, bytes or UTF-8
    RE re_test1(".........");
    CHECK(re_test1.FullMatch(utf8_string));
    RE re_test2("...", PCRECPP::UTF8());
    CHECK(re_test2.FullMatch(utf8_string));

    // Check that '.' matches one byte or UTF-8 character
    // according to the mode.
    string ss;
    RE re_test3("(.)");
    CHECK(re_test3.PartialMatch(utf8_string, &ss));
    CHECK_EQ(ss, string("\xe6"));
    RE re_test4("(.)", PCRECPP::UTF8());
    CHECK(re_test4.PartialMatch(utf8_string, &ss));
    CHECK_EQ(ss, string("\xe6\x97\xa5"));

    // Check that string matches itself in either mode
    RE re_test5(utf8_string);
    CHECK(re_test5.FullMatch(utf8_string));
    RE re_test6(utf8_string, PCRECPP::UTF8());
    CHECK(re_test6.FullMatch(utf8_string));

    // Check that pattern matches string only in UTF8 mode
    RE re_test7(utf8_pattern);
    CHECK(!re_test7.FullMatch(utf8_string));
    RE re_test8(utf8_pattern, PCRECPP::UTF8());
    CHECK(re_test8.FullMatch(utf8_string));
  }

  // Check that ungreedy, UTF8 regular expressions don't match when they
  // oughtn't -- see bug 82246.
  {
    // This code always worked.
    const char* pattern = "\\w+X";
    const string target = "a aX";
    RE match_sentence(pattern);
    RE match_sentence_re(pattern, PCRECPP::UTF8());

    CHECK(!match_sentence.FullMatch(target));
    CHECK(!match_sentence_re.FullMatch(target));
  }

  {
    const char* pattern = "(?U)\\w+X";
    const string target = "a aX";
    RE match_sentence(pattern);
    RE match_sentence_re(pattern, PCRECPP::UTF8());

    CHECK(!match_sentence.FullMatch(target));
    CHECK(!match_sentence_re.FullMatch(target));
  }
#endif  /* def SUPPORT_UTF8 */

  printf("Testing error reporting\n");

  { RE re("a\\1"); CHECK(!re.error().empty()); }
  {
    RE re("a[x");
    CHECK(!re.error().empty());
  }
  {
    RE re("a[z-a]");
    CHECK(!re.error().empty());
  }
  {
    RE re("a[[:foobar:]]");
    CHECK(!re.error().empty());
  }
  {
    RE re("a(b");
    CHECK(!re.error().empty());
  }
  {
    RE re("a\\");
    CHECK(!re.error().empty());
  }

  // Test that recursion is stopped
  TestRecursion();

  // Test Options
  if (getenv("VERBOSE_TEST") != NULL)
    VERBOSE_TEST  = true;
  TestOptions();

  // Test the constructors
  TestConstructors();

  // Done
  printf("OK\n");

  return 0;
}
/*autoconv-0001 C:\projects\pcre-8.31\pcrecpp_unittest.cc converted to UNITTESP*/
/*autoconv-0010 UNITTESP line: 37 added HAVE_CONFIG_H*/
/*autoconv-0011 UNITTESP line: 40 config.h replaced by CONFIG.h*/
/*autoconv-0011 UNITTESP line: 47 pcrecpp.h replaced by CPPH.h*/
/*autoconv-0013 UNITTESP line: 49 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 50 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 51 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 52 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 53 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 54 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 452 pcretest replaced by PCRETEST*/
/*autoconv-0013 UNITTESP line: 541 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 542 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 543 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 544 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 545 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 546 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 550 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 625 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 626 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 639 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 652 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 695 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 701 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 1205 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 1214 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 1221 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 1227 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 1238 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 UNITTESP line: 1248 pcrecpp replaced by PCRECPP*/
./ ADD NAME=REFCOUN8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function REFCOUN8(), which is an
auxiliary function that can be used to maintain a reference count in a compiled
pattern data block. This might be helpful in applications where the block is
shared by different users. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*           Maintain reference count             *
*************************************************/

/* The reference count is a 16-bit field, initialized to zero. It is not
possible to transfer a non-zero count from one host to a different host that
has a different byte order - though I can't see why anyone in their right mind
would ever want to do that!

Arguments:
  argument_re   points to compiled code
  adjust        value to add to the count

Returns:        the (possibly updated) count value (a non-negative number), or
                a negative error number
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
REFCOUN8(pcre *argument_re, int adjust)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_refcount(pcre16 *argument_re, int adjust)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)argument_re;
if (re == NULL) return PCRE_ERROR_NULL;
if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
re->ref_count = (-adjust > re->ref_count)? 0 :
                (adjust + re->ref_count > 65535)? 65535 :
                re->ref_count + adjust;
return re->ref_count;
}

/* End of REFCOUN8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_refcount.c converted to REFCOUN8*/
/*autoconv-0013 REFCOUN8 line: 41 pcre_refcount replaced by REFCOUN8*/
/*autoconv-0010 REFCOUN8 line: 48 added HAVE_CONFIG_H*/
/*autoconv-0011 REFCOUN8 line: 51 config.h replaced by CONFIG.h*/
/*autoconv-0011 REFCOUN8 line: 54 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 REFCOUN8 line: 76 pcre_refcount replaced by REFCOUN8*/
/*autoconv-0013 REFCOUN8 line: 92 pcre_refcount replaced by REFCOUN8*/
./ ADD NAME=PCRPOSIX 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module is a wrapper that provides a POSIX API to the underlying PCRE
functions. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif


/* Ensure that the PCREPOSIX_EXP_xxx macros are set appropriately for
compiling these functions. This must come before including PCRPOSIX.h, where
they are set for an application (using these functions) if they have not
previously been set. */

#if defined(_WIN32) && !defined(PCRE_STATIC)
#  define PCREPOSIX_EXP_DECL extern __declspec(dllexport)
#  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 "INTERNA8.h"
#include "POSIXH.h"


/* Table to translate PCRE compile time error codes into POSIX error codes. */

static const int eint[] = {
  0,           /* no error */
  REG_EESCAPE, /* \ at end of pattern */
  REG_EESCAPE, /* \c at end of pattern */
  REG_EESCAPE, /* unrecognized character follows \ */
  REG_BADBR,   /* numbers out of order in {} quantifier */
  /* 5 */
  REG_BADBR,   /* number too big in {} quantifier */
  REG_EBRACK,  /* missing terminating ] for character class */
  REG_ECTYPE,  /* invalid escape sequence in character class */
  REG_ERANGE,  /* range out of order in character class */
  REG_BADRPT,  /* nothing to repeat */
  /* 10 */
  REG_BADRPT,  /* operand of unlimited repeat could match the empty string */
  REG_ASSERT,  /* internal error: unexpected repeat */
  REG_BADPAT,  /* unrecognized character after (? */
  REG_BADPAT,  /* POSIX named classes are supported only within a class */
  REG_EPAREN,  /* missing ) */
  /* 15 */
  REG_ESUBREG, /* reference to non-existent subpattern */
  REG_INVARG,  /* erroffset passed as NULL */
  REG_INVARG,  /* unknown option bit(s) set */
  REG_EPAREN,  /* missing ) after comment */
  REG_ESIZE,   /* parentheses nested too deeply */
  /* 20 */
  REG_ESIZE,   /* regular expression too large */
  REG_ESPACE,  /* failed to get memory */
  REG_EPAREN,  /* unmatched parentheses */
  REG_ASSERT,  /* internal error: code overflow */
  REG_BADPAT,  /* unrecognized character after (?< */
  /* 25 */
  REG_BADPAT,  /* lookbehind assertion is not fixed length */
  REG_BADPAT,  /* malformed number or name after (?( */
  REG_BADPAT,  /* conditional group contains more than two branches */
  REG_BADPAT,  /* assertion expected after (?( */
  REG_BADPAT,  /* (?R or (?[+-]digits must be followed by ) */
  /* 30 */
  REG_ECTYPE,  /* unknown POSIX class name */
  REG_BADPAT,  /* POSIX collating elements are not supported */
  REG_INVARG,  /* this version of PCRE is not compiled with PCRE_UTF8 support */
  REG_BADPAT,  /* spare error */
  REG_BADPAT,  /* character value in \x{...} sequence is too large */
  /* 35 */
  REG_BADPAT,  /* invalid condition (?(0) */
  REG_BADPAT,  /* \C not allowed in lookbehind assertion */
  REG_EESCAPE, /* PCRE does not support \L, \l, \N, \U, or \u */
  REG_BADPAT,  /* number after (?C is > 255 */
  REG_BADPAT,  /* closing ) for (?C expected */
  /* 40 */
  REG_BADPAT,  /* recursive call could loop indefinitely */
  REG_BADPAT,  /* unrecognized character after (?P */
  REG_BADPAT,  /* syntax error in subpattern name (missing terminator) */
  REG_BADPAT,  /* two named subpatterns have the same name */
  REG_BADPAT,  /* invalid UTF-8 string */
  /* 45 */
  REG_BADPAT,  /* support for \P, \p, and \X has not been compiled */
  REG_BADPAT,  /* malformed \P or \p sequence */
  REG_BADPAT,  /* unknown property name after \P or \p */
  REG_BADPAT,  /* subpattern name is too long (maximum 32 characters) */
  REG_BADPAT,  /* too many named subpatterns (maximum 10,000) */
  /* 50 */
  REG_BADPAT,  /* repeated subpattern is too long */
  REG_BADPAT,  /* octal value is greater than \377 (not in UTF-8 mode) */
  REG_BADPAT,  /* internal error: overran compiling workspace */
  REG_BADPAT,  /* internal error: previously-checked referenced subpattern not found */
  REG_BADPAT,  /* DEFINE group contains more than one branch */
  /* 55 */
  REG_BADPAT,  /* repeating a DEFINE group is not allowed */
  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,  /* an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) */
  /* 60 */
  REG_BADPAT,  /* (*VERB) not recognized */
  REG_BADPAT,  /* number is too big */
  REG_BADPAT,  /* subpattern name expected */
  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,  /* (*MARK) must have an argument */
  REG_INVARG,  /* this version of PCRE is not compiled with PCRE_UCP support */
  REG_BADPAT,  /* \c must be followed by an ASCII character */
  REG_BADPAT,  /* \k is not followed by a braced, angle-bracketed, or quoted name */
  /* 70 */
  REG_BADPAT,  /* internal error: unknown opcode in find_fixedlength() */
  REG_BADPAT,  /* \N is not supported in a class */
  REG_BADPAT,  /* too many forward references */
  REG_BADPAT,  /* disallowed UTF-8/16 code point (>= 0xd800 && <= 0xdfff) */
  REG_BADPAT,  /* invalid UTF-16 string (should not occur) */
  /* 75 */
  REG_BADPAT,  /* overlong MARK name */
  REG_BADPAT   /* character value in \u.... sequence is too large */
};

/* Table of texts corresponding to POSIX error codes */

static const char *const pstring[] = {
  "",                                /* Dummy for value 0 */
  "internal error",                  /* REG_ASSERT */
  "invalid repeat counts in {}",     /* BADBR      */
  "pattern error",                   /* BADPAT     */
  "? * + invalid",                   /* BADRPT     */
  "unbalanced {}",                   /* EBRACE     */
  "unbalanced []",                   /* EBRACK     */
  "collation error - not relevant",  /* ECOLLATE   */
  "bad class",                       /* ECTYPE     */
  "bad escape sequence",             /* EESCAPE    */
  "empty expression",                /* EMPTY      */
  "unbalanced ()",                   /* EPAREN     */
  "bad range inside []",             /* ERANGE     */
  "expression too big",              /* ESIZE      */
  "failed to get memory",            /* ESPACE     */
  "bad back reference",              /* ESUBREG    */
  "bad argument",                    /* INVARG     */
  "match failed"                     /* NOMATCH    */
};




/*************************************************
*          Translate error code to string        *
*************************************************/

PCREPOSIX_EXP_DEFN size_t PCRE_CALL_CONVENTION
regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
{
const char *message, *addmessage;
size_t length, addlength;

message = (errcode >= (int)(sizeof(pstring)/sizeof(char *)))?
  "unknown error code" : pstring[errcode];
length = strlen(message) + 1;

addmessage = " at offset ";
addlength = (preg != NULL && (int)preg->re_erroffset != -1)?
  strlen(addmessage) + 6 : 0;

if (errbuf_size > 0)
  {
  if (addlength > 0 && errbuf_size >= length + addlength)
    sprintf(errbuf, "%s%s%-6d", message, addmessage, (int)preg->re_erroffset);
  else
    {
    strncpy(errbuf, message, errbuf_size - 1);
    errbuf[errbuf_size-1] = 0;
    }
  }

return length + addlength;
}




/*************************************************
*           Free store held by a regex           *
*************************************************/

PCREPOSIX_EXP_DEFN void PCRE_CALL_CONVENTION
regfree(regex_t *preg)
{
(PUBL(free))(preg->re_pcre);
}




/*************************************************
*            Compile a regular expression        *
*************************************************/

/*
Arguments:
  preg        points to a structure for recording the compiled expression
  pattern     the pattern to compile
  cflags      compilation flags

Returns:      0 on success
              various non-zero codes on failure
*/

PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION
regcomp(regex_t *preg, const char *pattern, int cflags)
{
const char *errorptr;
int erroffset;
int errorcode;
int options = 0;

if ((cflags & REG_ICASE) != 0)    options |= PCRE_CASELESS;
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,
  &erroffset, NULL);
preg->re_erroffset = erroffset;

/* Safety: if the error code is too big for the translation vector (which
should not happen, but we all make mistakes), return REG_BADPAT. */

if (preg->re_pcre == NULL)
  {
  return (errorcode < (int)(sizeof(eint)/sizeof(const int)))?
    eint[errorcode] : REG_BADPAT;
  }

(void)FULLINF8((const pcre *)preg->re_pcre, NULL, PCRE_INFO_CAPTURECOUNT,
  &(preg->re_nsub));
return 0;
}




/*************************************************
*              Match a regular expression        *
*************************************************/

/* Unfortunately, PCRE requires 3 ints of working space for each captured
substring, so we have to get and release working store instead of just using
the POSIX structures as was done in earlier releases when PCRE needed only 2
ints. However, if the number of possible capturing brackets is small, use a
block of store on the stack, to reduce the use of malloc/free. The threshold is
in a macro that can be changed at configure time.

If REG_NOSUB was specified at compile time, the PCRE_NO_AUTO_CAPTURE flag will
be set. When this is the case, the nmatch and pmatch arguments are ignored, and
the only result is yes/no/error. */

PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION
regexec(const regex_t *preg, const char *string, size_t nmatch,
  regmatch_t pmatch[], int eflags)
{
int rc, so, eo;
int options = 0;
int *ovector = NULL;
int small_ovector[POSIX_MALLOC_THRESHOLD * 3];
BOOL allocated_ovector = FALSE;
BOOL nosub =
  (((const pcre *)preg->re_pcre)->options & PCRE_NO_AUTO_CAPTURE) != 0;

if ((eflags & REG_NOTBOL) != 0) options |= PCRE_NOTBOL;
if ((eflags & REG_NOTEOL) != 0) options |= PCRE_NOTEOL;
if ((eflags & REG_NOTEMPTY) != 0) options |= PCRE_NOTEMPTY;

((regex_t *)preg)->re_erroffset = (size_t)(-1);  /* Only has meaning after compile */

/* When no string data is being returned, or no vector has been passed in which
to put it, ensure that nmatch is zero. Otherwise, ensure the vector for holding
the return data is large enough. */

if (nosub || pmatch == NULL) nmatch = 0;

else if (nmatch > 0)
  {
  if (nmatch <= POSIX_MALLOC_THRESHOLD)
    {
    ovector = &(small_ovector[0]);
    }
  else
    {
    if (nmatch > INT_MAX/(sizeof(int) * 3)) return REG_ESPACE;
    ovector = (int *)malloc(sizeof(int) * nmatch * 3);
    if (ovector == NULL) return REG_ESPACE;
    allocated_ovector = TRUE;
    }
  }

/* REG_STARTEND is a BSD extension, to allow for non-NUL-terminated strings.
The man page from OS X says "REG_STARTEND affects only the location of the
string, not how it is matched". That is why the "so" value is used to bump the
start location rather than being passed as a PCRE "starting offset". */

if ((eflags & REG_STARTEND) != 0)
  {
  so = pmatch[0].rm_so;
  eo = pmatch[0].rm_eo;
  }
else
  {
  so = 0;
  eo = (int)strlen(string);
  }

rc = PCREXEC8((const pcre *)preg->re_pcre, NULL, string + so, (eo - so),
  0, options, ovector, (int)(nmatch * 3));

if (rc == 0) rc = (int)nmatch;    /* All captured slots were filled in */

/* Successful match */

if (rc >= 0)
  {
  size_t i;
  if (!nosub)
    {
    for (i = 0; i < (size_t)rc; i++)
      {
      pmatch[i].rm_so = ovector[i*2];
      pmatch[i].rm_eo = ovector[i*2+1];
      }
    if (allocated_ovector) free(ovector);
    for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
    }
  return 0;
  }

/* Unsuccessful match */

if (allocated_ovector) free(ovector);
switch(rc)
  {
/* ========================================================================== */
  /* These cases are never obeyed. This is a fudge that causes a compile-time
  error if the vector eint, which is indexed by compile-time error number, is
  not the correct length. It seems to be the only way to do such a check at
  compile time, as the sizeof() operator does not work in the C preprocessor.
  As all the PCRE_ERROR_xxx values are negative, we can use 0 and 1. */

  case 0:
  case (sizeof(eint)/sizeof(int) == ERRCOUNT):
  return REG_ASSERT;
/* ========================================================================== */

  case PCRE_ERROR_NOMATCH: return REG_NOMATCH;
  case PCRE_ERROR_NULL: return REG_INVARG;
  case PCRE_ERROR_BADOPTION: return REG_INVARG;
  case PCRE_ERROR_BADMAGIC: return REG_INVARG;
  case PCRE_ERROR_UNKNOWN_NODE: return REG_ASSERT;
  case PCRE_ERROR_NOMEMORY: return REG_ESPACE;
  case PCRE_ERROR_MATCHLIMIT: return REG_ESPACE;
  case PCRE_ERROR_BADUTF8: return REG_INVARG;
  case PCRE_ERROR_BADUTF8_OFFSET: return REG_INVARG;
  case PCRE_ERROR_BADMODE: return REG_INVARG;
  default: return REG_ASSERT;
  }
}

/* End of PCRPOSIX.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcreposix.c converted to PCRPOSIX*/
/*autoconv-0010 PCRPOSIX line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 PCRPOSIX line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0013 PCRPOSIX line: 54 pcreposix replaced by PCRPOSIX*/
/*autoconv-0011 PCRPOSIX line: 68 pcre.h replaced by PCRE.h*/
/*autoconv-0011 PCRPOSIX line: 69 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0011 PCRPOSIX line: 70 pcreposix.h replaced by POSIXH.h*/
/*autoconv-0013 PCRPOSIX line: 287 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRPOSIX line: 365 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRPOSIX line: 419 pcreposix replaced by PCRPOSIX*/
./ ADD NAME=MAKETAB8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function MAKETAB8(), which builds
character tables for PCRE in the current locale. The file is compiled on its
own as part of the PCRE library. However, it is also included in the
compilation of DFTABLES.c, in which case the macro DFTABLES is defined. */


#ifndef DFTABLES
#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#  ifdef HAVE_CONFIG_H
#  include "CONFIG.h"
#  endif
#  include "INTERNA8.h"
#endif


/*************************************************
*           Create PCRE character tables         *
*************************************************/

/* This function builds a set of character tables for use by PCRE and returns
a pointer to them. They are build using the ctype functions, and consequently
their contents will depend upon the current locale setting. When compiled as
part of the library, the store is obtained via PUBL(malloc)(), but when
compiled inside DFTABLES, use malloc().

Arguments:   none
Returns:     pointer to the contiguous block of data
*/

#ifdef COMPILE_PCRE8
const unsigned char *
MAKETAB8(void)
#else
const unsigned char *
pcre16_maketables(void)
#endif
{
unsigned char *yield, *p;
int i;

#ifndef DFTABLES
yield = (unsigned char*)(PUBL(malloc))(tables_length);
#else
yield = (unsigned char*)malloc(tables_length);
#endif

if (yield == NULL) return NULL;
p = yield;

/* First comes the lower casing table */

for (i = 0; i < 256; i++) *p++ = tolower(i);

/* Next the case-flipping table */

for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);

/* Then the character class tables. Don't try to be clever and save effort on
exclusive ones - in some locales things may be different. Note that the table
for "space" includes everything "isspace" gives, including VT in the default
locale. This makes it work for the POSIX class [:space:]. Note also that it is
possible for a character to be alnum or alpha without being lower or upper,
such as "male and female ordinals" (\xAA and \xBA) in the fr_FR locale (at
least under Debian Linux's locales as of 12/2005). So we must test for alnum
specially. */

memset(p, 0, cbit_length);
for (i = 0; i < 256; i++)
  {
  if (isdigit(i)) p[cbit_digit  + i/8] |= 1 << (i&7);
  if (isupper(i)) p[cbit_upper  + i/8] |= 1 << (i&7);
  if (islower(i)) p[cbit_lower  + i/8] |= 1 << (i&7);
  if (isalnum(i)) p[cbit_word   + i/8] |= 1 << (i&7);
  if (i == '_')   p[cbit_word   + i/8] |= 1 << (i&7);
  if (isspace(i)) p[cbit_space  + i/8] |= 1 << (i&7);
  if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7);
  if (isgraph(i)) p[cbit_graph  + i/8] |= 1 << (i&7);
  if (isprint(i)) p[cbit_print  + i/8] |= 1 << (i&7);
  if (ispunct(i)) p[cbit_punct  + i/8] |= 1 << (i&7);
  if (iscntrl(i)) p[cbit_cntrl  + i/8] |= 1 << (i&7);
  }
p += cbit_length;

/* Finally, the character type table. In this, we exclude VT from the white
space chars, because Perl doesn't recognize it as such for \s and for comments
within regexes. */

for (i = 0; i < 256; i++)
  {
  int x = 0;
  if (i != 0x0b && isspace(i)) x += ctype_space;
  if (isalpha(i)) x += ctype_letter;
  if (isdigit(i)) x += ctype_digit;
  if (isxdigit(i)) x += ctype_xdigit;
  if (isalnum(i) || i == '_') x += ctype_word;

  /* Note: strchr includes the terminating zero in the characters it considers.
  In this instance, that is ok because we want binary zero to be flagged as a
  meta-character, which in this sense is any character that terminates a run
  of data characters. */

  if (strchr("\\*+?{.$|()[", i) != 0) x += ctype_meta;
  *p++ = x;
  }

return yield;
}

/* End of MAKETAB8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_maketables.c converted to MAKETAB8*/
/*autoconv-0013 MAKETAB8 line: 41 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0013 MAKETAB8 line: 44 dftables replaced by DFTABLES*/
/*autoconv-0010 MAKETAB8 line: 49 added HAVE_CONFIG_H*/
/*autoconv-0011 MAKETAB8 line: 52 config.h replaced by CONFIG.h*/
/*autoconv-0011 MAKETAB8 line: 54 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 MAKETAB8 line: 66 dftables replaced by DFTABLES*/
/*autoconv-0013 MAKETAB8 line: 74 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0013 MAKETAB8 line: 151 pcre_maketables replaced by MAKETAB8*/
./ ADD NAME=JITCOMP8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

  The machine code generator part (this module) was written by Zoltan Herczeg
                      Copyright (c) 2010-2012

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

#ifdef SUPPORT_JIT

/* All-in-one: Since we use the JIT compiler only from here,
we just include it. This way we don't need to touch the build
system files. */

#define SLJIT_MALLOC(size) (PUBL(malloc))(size)
#define SLJIT_FREE(ptr) (PUBL(free))(ptr)
#define SLJIT_CONFIG_AUTO 1
#define SLJIT_CONFIG_STATIC 1
#define SLJIT_VERBOSE 0
#define SLJIT_DEBUG 0

#include "sljit/sljitLir.c"

#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
#error Unsupported architecture
#endif

/* Allocate memory on the stack. Fast, but limited size. */
#define LOCAL_SPACE_SIZE 32768

#define STACK_GROWTH_RATE 8192

/* Enable to check that the allocation could destroy temporaries. */
#if defined SLJIT_DEBUG && SLJIT_DEBUG
#define DESTROY_REGISTERS 1
#endif

/*
Short summary about the backtracking mechanism empolyed by the jit code generator:

The code generator follows the recursive nature of the PERL compatible regular
expressions. The basic blocks of regular expressions are condition checkers
whose execute different commands depending on the result of the condition check.
The relationship between the operators can be horizontal (concatenation) and
vertical (sub-expression) (See struct backtrack_common for more details).

  'ab' - 'a' and 'b' regexps are concatenated
  'a+' - 'a' is the sub-expression of the '+' operator

The condition checkers are boolean (true/false) checkers. Machine code is generated
for the checker itself and for the actions depending on the result of the checker.
The 'true' case is called as the try path (expected path), and the other is called as
the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
branches on the try path.

 Greedy star operator (*) :
   Try path: match happens.
   Backtrack path: match failed.
 Non-greedy star operator (*?) :
   Try path: no need to perform a match.
   Backtrack path: match is required.

The following example shows how the code generated for a capturing bracket
with two alternatives. Let A, B, C, D are arbirary regular expressions, and
we have the following regular expression:

   A(B|C)D

The generated code will be the following:

 A try path
 '(' try path (pushing arguments to the stack)
 B try path
 ')' try path (pushing arguments to the stack)
 D try path
 return with successful match

 D backtrack path
 ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
 B backtrack path
 C expected path
 jump to D try path
 C backtrack path
 A backtrack path

 Notice, that the order of backtrack code paths are the opposite of the fast
 code paths. In this way the topmost value on the stack is always belong
 to the current backtrack code path. The backtrack path must check
 whether there is a next alternative. If so, it needs to jump back to
 the try path eventually. Otherwise it needs to clear out its own stack
 frame and continue the execution on the backtrack code paths.
*/

/*
Saved stack frames:

Atomic blocks and asserts require reloading the values of local variables
when the backtrack mechanism performed. Because of OP_RECURSE, the locals
are not necessarly known in compile time, thus we need a dynamic restore
mechanism.

The stack frames are stored in a chain list, and have the following format:
([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]

Thus we can restore the locals to a particular point in the stack.
*/

typedef struct jit_arguments {
  /* Pointers first. */
  struct sljit_stack *stack;
  const pcre_uchar *str;
  const pcre_uchar *begin;
  const pcre_uchar *end;
  int *offsets;
  pcre_uchar *uchar_ptr;
  pcre_uchar *mark_ptr;
  /* Everything else after. */
  int offsetcount;
  int calllimit;
  pcre_uint8 notbol;
  pcre_uint8 noteol;
  pcre_uint8 notempty;
  pcre_uint8 notempty_atstart;
} jit_arguments;

typedef struct executable_functions {
  void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
  PUBL(jit_callback) callback;
  void *userdata;
  sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
} executable_functions;

typedef struct jump_list {
  struct sljit_jump *jump;
  struct jump_list *next;
} jump_list;

enum stub_types { stack_alloc };

typedef struct stub_list {
  enum stub_types type;
  int data;
  struct sljit_jump *start;
  struct sljit_label *leave;
  struct stub_list *next;
} stub_list;

typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);

/* The following structure is the key data type for the recursive
code generator. It is allocated by compile_trypath, and contains
the aguments for compile_backtrackpath. Must be the first member
of its descendants. */
typedef struct backtrack_common {
  /* Concatenation stack. */
  struct backtrack_common *prev;
  jump_list *nextbacktracks;
  /* Internal stack (for component operators). */
  struct backtrack_common *top;
  jump_list *topbacktracks;
  /* Opcode pointer. */
  pcre_uchar *cc;
} backtrack_common;

typedef struct assert_backtrack {
  backtrack_common common;
  jump_list *condfailed;
  /* Less than 0 (-1) if a frame is not needed. */
  int framesize;
  /* Points to our private memory word on the stack. */
  int localptr;
  /* For iterators. */
  struct sljit_label *trypath;
} assert_backtrack;

typedef struct bracket_backtrack {
  backtrack_common common;
  /* Where to coninue if an alternative is successfully matched. */
  struct sljit_label *alttrypath;
  /* For rmin and rmax iterators. */
  struct sljit_label *recursivetrypath;
  /* For greedy ? operator. */
  struct sljit_label *zerotrypath;
  /* Contains the branches of a failed condition. */
  union {
    /* Both for OP_COND, OP_SCOND. */
    jump_list *condfailed;
    assert_backtrack *assert;
    /* For OP_ONCE. -1 if not needed. */
    int framesize;
  } u;
  /* Points to our private memory word on the stack. */
  int localptr;
} bracket_backtrack;

typedef struct bracketpos_backtrack {
  backtrack_common common;
  /* Points to our private memory word on the stack. */
  int localptr;
  /* Reverting stack is needed. */
  int framesize;
  /* Allocated stack size. */
  int stacksize;
} bracketpos_backtrack;

typedef struct braminzero_backtrack {
  backtrack_common common;
  struct sljit_label *trypath;
} braminzero_backtrack;

typedef struct iterator_backtrack {
  backtrack_common common;
  /* Next iteration. */
  struct sljit_label *trypath;
} iterator_backtrack;

typedef struct recurse_entry {
  struct recurse_entry *next;
  /* Contains the function entry. */
  struct sljit_label *entry;
  /* Collects the calls until the function is not created. */
  jump_list *calls;
  /* Points to the starting opcode. */
  int start;
} recurse_entry;

typedef struct recurse_backtrack {
  backtrack_common common;
} recurse_backtrack;

typedef struct compiler_common {
  struct sljit_compiler *compiler;
  pcre_uchar *start;

  /* Opcode local area direct map. */
  int *localptrs;
  int cbraptr;
  /* OVector starting point. Must be divisible by 2. */
  int ovector_start;
  /* Last known position of the requested byte. */
  int req_char_ptr;
  /* Head of the last recursion. */
  int recursive_head;
  /* First inspected character for partial matching. */
  int start_used_ptr;
  /* Starting pointer for partial soft matches. */
  int hit_start;
  /* End pointer of the first line. */
  int first_line_end;
  /* Points to the marked string. */
  int mark_ptr;

  /* Other  */
  const pcre_uint8 *fcc;
  sljit_w lcc;
  int mode;
  int nltype;
  int newline;
  int bsr_nltype;
  int endonly;
  BOOL has_set_som;
  sljit_w ctypes;
  sljit_uw name_table;
  sljit_w name_count;
  sljit_w name_entry_size;

  /* Labels and jump lists. */
  struct sljit_label *partialmatchlabel;
  struct sljit_label *leavelabel;
  struct sljit_label *acceptlabel;
  stub_list *stubs;
  recurse_entry *entries;
  recurse_entry *currententry;
  jump_list *partialmatch;
  jump_list *leave;
  jump_list *accept;
  jump_list *calllimit;
  jump_list *stackalloc;
  jump_list *revertframes;
  jump_list *wordboundary;
  jump_list *anynewline;
  jump_list *hspace;
  jump_list *vspace;
  jump_list *casefulcmp;
  jump_list *caselesscmp;
  BOOL jscript_compat;
#ifdef SUPPORT_UTF
  BOOL utf;
#ifdef SUPPORT_UCP
  BOOL use_ucp;
#endif
  jump_list *utfreadchar;
#ifdef COMPILE_PCRE8
  jump_list *utfreadtype8;
#endif
#endif /* SUPPORT_UTF */
#ifdef SUPPORT_UCP
  jump_list *getucd;
#endif
} compiler_common;

/* For byte_sequence_compare. */

typedef struct compare_context {
  int length;
  int sourcereg;
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
  int ucharptr;
  union {
    sljit_i asint;
    sljit_uh asushort;
#ifdef COMPILE_PCRE8
    sljit_ub asbyte;
    sljit_ub asuchars[4];
#else
#ifdef COMPILE_PCRE16
    sljit_uh asuchars[2];
#endif
#endif
  } c;
  union {
    sljit_i asint;
    sljit_uh asushort;
#ifdef COMPILE_PCRE8
    sljit_ub asbyte;
    sljit_ub asuchars[4];
#else
#ifdef COMPILE_PCRE16
    sljit_uh asuchars[2];
#endif
#endif
  } oc;
#endif
} compare_context;

enum {
  frame_end = 0,
  frame_setstrbegin = -1,
  frame_setmark = -2
};

/* Undefine sljit macros. */
#undef CMP

/* Used for accessing the elements of the stack. */
#define STACK(i)      ((-(i) - 1) * (int)sizeof(sljit_w))

#define TMP1          SLJIT_TEMPORARY_REG1
#define TMP2          SLJIT_TEMPORARY_REG3
#define TMP3          SLJIT_TEMPORARY_EREG2
#define STR_PTR       SLJIT_SAVED_REG1
#define STR_END       SLJIT_SAVED_REG2
#define STACK_TOP     SLJIT_TEMPORARY_REG2
#define STACK_LIMIT   SLJIT_SAVED_REG3
#define ARGUMENTS     SLJIT_SAVED_EREG1
#define CALL_COUNT    SLJIT_SAVED_EREG2
#define RETURN_ADDR   SLJIT_TEMPORARY_EREG1

/* Locals layout. */
/* These two locals can be used by the current opcode. */
#define LOCALS0          (0 * sizeof(sljit_w))
#define LOCALS1          (1 * sizeof(sljit_w))
/* Two local variables for possessive quantifiers (char1 cannot use them). */
#define POSSESSIVE0      (2 * sizeof(sljit_w))
#define POSSESSIVE1      (3 * sizeof(sljit_w))
/* Max limit of recursions. */
#define CALL_LIMIT       (4 * sizeof(sljit_w))
/* The output vector is stored on the stack, and contains pointers
to characters. The vector data is divided into two groups: the first
group contains the start / end character pointers, and the second is
the start pointers when the end of the capturing group has not yet reached. */
#define OVECTOR_START    (common->ovector_start)
#define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))
#define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))
#define PRIV_DATA(cc)    (common->localptrs[(cc) - common->start])

#ifdef COMPILE_PCRE8
#define MOV_UCHAR  SLJIT_MOV_UB
#define MOVU_UCHAR SLJIT_MOVU_UB
#else
#ifdef COMPILE_PCRE16
#define MOV_UCHAR  SLJIT_MOV_UH
#define MOVU_UCHAR SLJIT_MOVU_UH
#else
#error Unsupported compiling mode
#endif
#endif

/* Shortcuts. */
#define DEFINE_COMPILER \
  struct sljit_compiler *compiler = common->compiler
#define OP1(op, dst, dstw, src, srcw) \
  sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
  sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
#define LABEL() \
  sljit_emit_label(compiler)
#define JUMP(type) \
  sljit_emit_jump(compiler, (type))
#define JUMPTO(type, label) \
  sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
#define JUMPHERE(jump) \
  sljit_set_label((jump), sljit_emit_label(compiler))
#define CMP(type, src1, src1w, src2, src2w) \
  sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
#define CMPTO(type, src1, src1w, src2, src2w, label) \
  sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
#define COND_VALUE(op, dst, dstw, type) \
  sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
#define GET_LOCAL_BASE(dst, dstw, offset) \
  sljit_get_local_base(compiler, (dst), (dstw), (offset))

static pcre_uchar* bracketend(pcre_uchar* cc)
{
SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
do cc += GET(cc, 1); while (*cc == OP_ALT);
SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
cc += 1 + LINK_SIZE;
return cc;
}

/* Functions whose might need modification for all new supported opcodes:
 next_opcode
 get_localspace
 set_localptrs
 get_framesize
 init_frame
 get_localsize
 copy_locals
 compile_trypath
 compile_backtrackpath
*/

static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
{
SLJIT_UNUSED_ARG(common);
switch(*cc)
  {
  case OP_SOD:
  case OP_SOM:
  case OP_SET_SOM:
  case OP_NOT_WORD_BOUNDARY:
  case OP_WORD_BOUNDARY:
  case OP_NOT_DIGIT:
  case OP_DIGIT:
  case OP_NOT_WHITESPACE:
  case OP_WHITESPACE:
  case OP_NOT_WORDCHAR:
  case OP_WORDCHAR:
  case OP_ANY:
  case OP_ALLANY:
  case OP_ANYNL:
  case OP_NOT_HSPACE:
  case OP_HSPACE:
  case OP_NOT_VSPACE:
  case OP_VSPACE:
  case OP_EXTUNI:
  case OP_EODN:
  case OP_EOD:
  case OP_CIRC:
  case OP_CIRCM:
  case OP_DOLL:
  case OP_DOLLM:
  case OP_TYPESTAR:
  case OP_TYPEMINSTAR:
  case OP_TYPEPLUS:
  case OP_TYPEMINPLUS:
  case OP_TYPEQUERY:
  case OP_TYPEMINQUERY:
  case OP_TYPEPOSSTAR:
  case OP_TYPEPOSPLUS:
  case OP_TYPEPOSQUERY:
  case OP_CRSTAR:
  case OP_CRMINSTAR:
  case OP_CRPLUS:
  case OP_CRMINPLUS:
  case OP_CRQUERY:
  case OP_CRMINQUERY:
  case OP_DEF:
  case OP_BRAZERO:
  case OP_BRAMINZERO:
  case OP_BRAPOSZERO:
  case OP_COMMIT:
  case OP_FAIL:
  case OP_ACCEPT:
  case OP_ASSERT_ACCEPT:
  case OP_SKIPZERO:
  return cc + 1;

  case OP_ANYBYTE:
#ifdef SUPPORT_UTF
  if (common->utf) return NULL;
#endif
  return cc + 1;

  case OP_CHAR:
  case OP_CHARI:
  case OP_NOT:
  case OP_NOTI:
  case OP_STAR:
  case OP_MINSTAR:
  case OP_PLUS:
  case OP_MINPLUS:
  case OP_QUERY:
  case OP_MINQUERY:
  case OP_POSSTAR:
  case OP_POSPLUS:
  case OP_POSQUERY:
  case OP_STARI:
  case OP_MINSTARI:
  case OP_PLUSI:
  case OP_MINPLUSI:
  case OP_QUERYI:
  case OP_MINQUERYI:
  case OP_POSSTARI:
  case OP_POSPLUSI:
  case OP_POSQUERYI:
  case OP_NOTSTAR:
  case OP_NOTMINSTAR:
  case OP_NOTPLUS:
  case OP_NOTMINPLUS:
  case OP_NOTQUERY:
  case OP_NOTMINQUERY:
  case OP_NOTPOSSTAR:
  case OP_NOTPOSPLUS:
  case OP_NOTPOSQUERY:
  case OP_NOTSTARI:
  case OP_NOTMINSTARI:
  case OP_NOTPLUSI:
  case OP_NOTMINPLUSI:
  case OP_NOTQUERYI:
  case OP_NOTMINQUERYI:
  case OP_NOTPOSSTARI:
  case OP_NOTPOSPLUSI:
  case OP_NOTPOSQUERYI:
  cc += 2;
#ifdef SUPPORT_UTF
  if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
  return cc;

  case OP_UPTO:
  case OP_MINUPTO:
  case OP_EXACT:
  case OP_POSUPTO:
  case OP_UPTOI:
  case OP_MINUPTOI:
  case OP_EXACTI:
  case OP_POSUPTOI:
  case OP_NOTUPTO:
  case OP_NOTMINUPTO:
  case OP_NOTEXACT:
  case OP_NOTPOSUPTO:
  case OP_NOTUPTOI:
  case OP_NOTMINUPTOI:
  case OP_NOTEXACTI:
  case OP_NOTPOSUPTOI:
  cc += 2 + IMM2_SIZE;
#ifdef SUPPORT_UTF
  if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
  return cc;

  case OP_NOTPROP:
  case OP_PROP:
  return cc + 1 + 2;

  case OP_TYPEUPTO:
  case OP_TYPEMINUPTO:
  case OP_TYPEEXACT:
  case OP_TYPEPOSUPTO:
  case OP_REF:
  case OP_REFI:
  case OP_CREF:
  case OP_NCREF:
  case OP_RREF:
  case OP_NRREF:
  case OP_CLOSE:
  cc += 1 + IMM2_SIZE;
  return cc;

  case OP_CRRANGE:
  case OP_CRMINRANGE:
  return cc + 1 + 2 * IMM2_SIZE;

  case OP_CLASS:
  case OP_NCLASS:
  return cc + 1 + 32 / sizeof(pcre_uchar);

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
  case OP_XCLASS:
  return cc + GET(cc, 1);
#endif

  case OP_RECURSE:
  case OP_ASSERT:
  case OP_ASSERT_NOT:
  case OP_ASSERTBACK:
  case OP_ASSERTBACK_NOT:
  case OP_REVERSE:
  case OP_ONCE:
  case OP_ONCE_NC:
  case OP_BRA:
  case OP_BRAPOS:
  case OP_COND:
  case OP_SBRA:
  case OP_SBRAPOS:
  case OP_SCOND:
  case OP_ALT:
  case OP_KET:
  case OP_KETRMAX:
  case OP_KETRMIN:
  case OP_KETRPOS:
  return cc + 1 + LINK_SIZE;

  case OP_CBRA:
  case OP_CBRAPOS:
  case OP_SCBRA:
  case OP_SCBRAPOS:
  return cc + 1 + LINK_SIZE + IMM2_SIZE;

  case OP_MARK:
  return cc + 1 + 2 + cc[1];

  default:
  return NULL;
  }
}

static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
{
int localspace = 0;
pcre_uchar *alternative;
/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
while (cc < ccend)
  {
  switch(*cc)
    {
    case OP_SET_SOM:
    common->has_set_som = TRUE;
    cc += 1;
    break;

    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_BRAPOS:
    case OP_SBRA:
    case OP_SBRAPOS:
    case OP_SCOND:
    localspace += sizeof(sljit_w);
    cc += 1 + LINK_SIZE;
    break;

    case OP_CBRAPOS:
    case OP_SCBRAPOS:
    localspace += sizeof(sljit_w);
    cc += 1 + LINK_SIZE + IMM2_SIZE;
    break;

    case OP_COND:
    /* Might be a hidden SCOND. */
    alternative = cc + GET(cc, 1);
    if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
      localspace += sizeof(sljit_w);
    cc += 1 + LINK_SIZE;
    break;

    case OP_RECURSE:
    /* Set its value only once. */
    if (common->recursive_head == 0)
      {
      common->recursive_head = common->ovector_start;
      common->ovector_start += sizeof(sljit_w);
      }
    cc += 1 + LINK_SIZE;
    break;

    case OP_MARK:
    if (common->mark_ptr == 0)
      {
      common->mark_ptr = common->ovector_start;
      common->ovector_start += sizeof(sljit_w);
      }
    cc += 1 + 2 + cc[1];
    break;

    default:
    cc = next_opcode(common, cc);
    if (cc == NULL)
      return -1;
    break;
    }
  }
return localspace;
}

static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend)
{
pcre_uchar *cc = common->start;
pcre_uchar *alternative;
while (cc < ccend)
  {
  switch(*cc)
    {
    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_BRAPOS:
    case OP_SBRA:
    case OP_SBRAPOS:
    case OP_SCOND:
    common->localptrs[cc - common->start] = localptr;
    localptr += sizeof(sljit_w);
    cc += 1 + LINK_SIZE;
    break;

    case OP_CBRAPOS:
    case OP_SCBRAPOS:
    common->localptrs[cc - common->start] = localptr;
    localptr += sizeof(sljit_w);
    cc += 1 + LINK_SIZE + IMM2_SIZE;
    break;

    case OP_COND:
    /* Might be a hidden SCOND. */
    alternative = cc + GET(cc, 1);
    if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
      {
      common->localptrs[cc - common->start] = localptr;
      localptr += sizeof(sljit_w);
      }
    cc += 1 + LINK_SIZE;
    break;

    default:
    cc = next_opcode(common, cc);
    SLJIT_ASSERT(cc != NULL);
    break;
    }
  }
}

/* Returns with -1 if no need for frame. */
static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive)
{
pcre_uchar *ccend = bracketend(cc);
int length = 0;
BOOL possessive = FALSE;
BOOL setsom_found = recursive;
BOOL setmark_found = recursive;

if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
  {
  length = 3;
  possessive = TRUE;
  }

cc = next_opcode(common, cc);
SLJIT_ASSERT(cc != NULL);
while (cc < ccend)
  switch(*cc)
    {
    case OP_SET_SOM:
    SLJIT_ASSERT(common->has_set_som);
    if (!setsom_found)
      {
      length += 2;
      setsom_found = TRUE;
      }
    cc += 1;
    break;

    case OP_MARK:
    SLJIT_ASSERT(common->mark_ptr != 0);
    if (!setmark_found)
      {
      length += 2;
      setmark_found = TRUE;
      }
    cc += 1 + 2 + cc[1];
    break;

    case OP_RECURSE:
    if (common->has_set_som && !setsom_found)
      {
      length += 2;
      setsom_found = TRUE;
      }
    if (common->mark_ptr != 0 && !setmark_found)
      {
      length += 2;
      setmark_found = TRUE;
      }
    cc += 1 + LINK_SIZE;
    break;

    case OP_CBRA:
    case OP_CBRAPOS:
    case OP_SCBRA:
    case OP_SCBRAPOS:
    length += 3;
    cc += 1 + LINK_SIZE + IMM2_SIZE;
    break;

    default:
    cc = next_opcode(common, cc);
    SLJIT_ASSERT(cc != NULL);
    break;
    }

/* Possessive quantifiers can use a special case. */
if (SLJIT_UNLIKELY(possessive) && length == 3)
  return -1;

if (length > 0)
  return length + 1;
return -1;
}

static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive)
{
DEFINE_COMPILER;
pcre_uchar *ccend = bracketend(cc);
BOOL setsom_found = recursive;
BOOL setmark_found = recursive;
int offset;

/* >= 1 + shortest item size (2) */
SLJIT_UNUSED_ARG(stacktop);
SLJIT_ASSERT(stackpos >= stacktop + 2);

stackpos = STACK(stackpos);
if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
  cc = next_opcode(common, cc);
SLJIT_ASSERT(cc != NULL);
while (cc < ccend)
  switch(*cc)
    {
    case OP_SET_SOM:
    SLJIT_ASSERT(common->has_set_som);
    if (!setsom_found)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
      stackpos += (int)sizeof(sljit_w);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
      stackpos += (int)sizeof(sljit_w);
      setsom_found = TRUE;
      }
    cc += 1;
    break;

    case OP_MARK:
    SLJIT_ASSERT(common->mark_ptr != 0);
    if (!setmark_found)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark);
      stackpos += (int)sizeof(sljit_w);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
      stackpos += (int)sizeof(sljit_w);
      setmark_found = TRUE;
      }
    cc += 1 + 2 + cc[1];
    break;

    case OP_RECURSE:
    if (common->has_set_som && !setsom_found)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
      stackpos += (int)sizeof(sljit_w);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
      stackpos += (int)sizeof(sljit_w);
      setsom_found = TRUE;
      }
    if (common->mark_ptr != 0 && !setmark_found)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark);
      stackpos += (int)sizeof(sljit_w);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
      stackpos += (int)sizeof(sljit_w);
      setmark_found = TRUE;
      }
    cc += 1 + LINK_SIZE;
    break;

    case OP_CBRA:
    case OP_CBRAPOS:
    case OP_SCBRA:
    case OP_SCBRAPOS:
    offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
    stackpos += (int)sizeof(sljit_w);
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
    stackpos += (int)sizeof(sljit_w);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
    stackpos += (int)sizeof(sljit_w);

    cc += 1 + LINK_SIZE + IMM2_SIZE;
    break;

    default:
    cc = next_opcode(common, cc);
    SLJIT_ASSERT(cc != NULL);
    break;
    }

OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end);
SLJIT_ASSERT(stackpos == STACK(stacktop));
}

static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
{
int localsize = 2;
pcre_uchar *alternative;
/* Calculate the sum of the local variables. */
while (cc < ccend)
  {
  switch(*cc)
    {
    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_BRAPOS:
    case OP_SBRA:
    case OP_SBRAPOS:
    case OP_SCOND:
    localsize++;
    cc += 1 + LINK_SIZE;
    break;

    case OP_CBRA:
    case OP_SCBRA:
    localsize++;
    cc += 1 + LINK_SIZE + IMM2_SIZE;
    break;

    case OP_CBRAPOS:
    case OP_SCBRAPOS:
    localsize += 2;
    cc += 1 + LINK_SIZE + IMM2_SIZE;
    break;

    case OP_COND:
    /* Might be a hidden SCOND. */
    alternative = cc + GET(cc, 1);
    if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
      localsize++;
    cc += 1 + LINK_SIZE;
    break;

    default:
    cc = next_opcode(common, cc);
    SLJIT_ASSERT(cc != NULL);
    break;
    }
  }
SLJIT_ASSERT(cc == ccend);
return localsize;
}

static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
  BOOL save, int stackptr, int stacktop)
{
DEFINE_COMPILER;
int srcw[2];
int count;
BOOL tmp1next = TRUE;
BOOL tmp1empty = TRUE;
BOOL tmp2empty = TRUE;
pcre_uchar *alternative;
enum {
  start,
  loop,
  end
} status;

status = save ? start : loop;
stackptr = STACK(stackptr - 2);
stacktop = STACK(stacktop - 1);

if (!save)
  {
  stackptr += sizeof(sljit_w);
  if (stackptr < stacktop)
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
    stackptr += sizeof(sljit_w);
    tmp1empty = FALSE;
    }
  if (stackptr < stacktop)
    {
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
    stackptr += sizeof(sljit_w);
    tmp2empty = FALSE;
    }
  /* The tmp1next must be TRUE in either way. */
  }

while (status != end)
  {
  count = 0;
  switch(status)
    {
    case start:
    SLJIT_ASSERT(save && common->recursive_head != 0);
    count = 1;
    srcw[0] = common->recursive_head;
    status = loop;
    break;

    case loop:
    if (cc >= ccend)
      {
      status = end;
      break;
      }

    switch(*cc)
      {
      case OP_ASSERT:
      case OP_ASSERT_NOT:
      case OP_ASSERTBACK:
      case OP_ASSERTBACK_NOT:
      case OP_ONCE:
      case OP_ONCE_NC:
      case OP_BRAPOS:
      case OP_SBRA:
      case OP_SBRAPOS:
      case OP_SCOND:
      count = 1;
      srcw[0] = PRIV_DATA(cc);
      SLJIT_ASSERT(srcw[0] != 0);
      cc += 1 + LINK_SIZE;
      break;

      case OP_CBRA:
      case OP_SCBRA:
      count = 1;
      srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
      cc += 1 + LINK_SIZE + IMM2_SIZE;
      break;

      case OP_CBRAPOS:
      case OP_SCBRAPOS:
      count = 2;
      srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
      srcw[0] = PRIV_DATA(cc);
      SLJIT_ASSERT(srcw[0] != 0);
      cc += 1 + LINK_SIZE + IMM2_SIZE;
      break;

      case OP_COND:
      /* Might be a hidden SCOND. */
      alternative = cc + GET(cc, 1);
      if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
        {
        count = 1;
        srcw[0] = PRIV_DATA(cc);
        SLJIT_ASSERT(srcw[0] != 0);
        }
      cc += 1 + LINK_SIZE;
      break;

      default:
      cc = next_opcode(common, cc);
      SLJIT_ASSERT(cc != NULL);
      break;
      }
    break;

    case end:
    SLJIT_ASSERT_STOP();
    break;
    }

  while (count > 0)
    {
    count--;
    if (save)
      {
      if (tmp1next)
        {
        if (!tmp1empty)
          {
          OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
          stackptr += sizeof(sljit_w);
          }
        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
        tmp1empty = FALSE;
        tmp1next = FALSE;
        }
      else
        {
        if (!tmp2empty)
          {
          OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
          stackptr += sizeof(sljit_w);
          }
        OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
        tmp2empty = FALSE;
        tmp1next = TRUE;
        }
      }
    else
      {
      if (tmp1next)
        {
        SLJIT_ASSERT(!tmp1empty);
        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
        tmp1empty = stackptr >= stacktop;
        if (!tmp1empty)
          {
          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
          stackptr += sizeof(sljit_w);
          }
        tmp1next = FALSE;
        }
      else
        {
        SLJIT_ASSERT(!tmp2empty);
        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
        tmp2empty = stackptr >= stacktop;
        if (!tmp2empty)
          {
          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
          stackptr += sizeof(sljit_w);
          }
        tmp1next = TRUE;
        }
      }
    }
  }

if (save)
  {
  if (tmp1next)
    {
    if (!tmp1empty)
      {
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
      stackptr += sizeof(sljit_w);
      }
    if (!tmp2empty)
      {
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
      stackptr += sizeof(sljit_w);
      }
    }
  else
    {
    if (!tmp2empty)
      {
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
      stackptr += sizeof(sljit_w);
      }
    if (!tmp1empty)
      {
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
      stackptr += sizeof(sljit_w);
      }
    }
  }
SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
}

static SLJIT_INLINE BOOL ispowerof2(unsigned int value)
{
return (value & (value - 1)) == 0;
}

static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
{
while (list)
  {
  /* sljit_set_label is clever enough to do nothing
  if either the jump or the label is NULL */
  sljit_set_label(list->jump, label);
  list = list->next;
  }
}

static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
{
jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
if (list_item)
  {
  list_item->next = *list;
  list_item->jump = jump;
  *list = list_item;
  }
}

static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start)
{
DEFINE_COMPILER;
stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));

if (list_item)
  {
  list_item->type = type;
  list_item->data = data;
  list_item->start = start;
  list_item->leave = LABEL();
  list_item->next = common->stubs;
  common->stubs = list_item;
  }
}

static void flush_stubs(compiler_common *common)
{
DEFINE_COMPILER;
stub_list* list_item = common->stubs;

while (list_item)
  {
  JUMPHERE(list_item->start);
  switch(list_item->type)
    {
    case stack_alloc:
    add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
    break;
    }
  JUMPTO(SLJIT_JUMP, list_item->leave);
  list_item = list_item->next;
  }
common->stubs = NULL;
}

static SLJIT_INLINE void decrease_call_count(compiler_common *common)
{
DEFINE_COMPILER;

OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);
add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
}

static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
{
/* May destroy all locals and registers except TMP2. */
DEFINE_COMPILER;

OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
#ifdef DESTROY_REGISTERS
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
#endif
add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
}

static SLJIT_INLINE void free_stack(compiler_common *common, int size)
{
DEFINE_COMPILER;
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
}

static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
{
DEFINE_COMPILER;
struct sljit_label *loop;
int i;
/* At this point we can freely use all temporary registers. */
/* TMP1 returns with begin - 1. */
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));
if (length < 8)
  {
  for (i = 0; i < length; i++)
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
  }
else
  {
  GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, OVECTOR_START - sizeof(sljit_w));
  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
  loop = LABEL();
  OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
  JUMPTO(SLJIT_C_NOT_ZERO, loop);
  }
}

static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
{
DEFINE_COMPILER;
struct sljit_label *loop;
struct sljit_jump *earlyexit;

/* At this point we can freely use all registers. */
OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);

OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
if (common->mark_ptr != 0)
  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
if (common->mark_ptr != 0)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0);
OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START);
/* Unlikely, but possible */
earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
loop = LABEL();
OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
/* Copy the integer value to the output buffer */
#ifdef COMPILE_PCRE16
OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
#endif
OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_C_NOT_ZERO, loop);
JUMPHERE(earlyexit);

/* Calculate the return value, which is the maximum ovector value. */
if (topbracket > 1)
  {
  GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);

  /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
  loop = LABEL();
  OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w)));
  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
  CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop);
  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0);
  }
else
  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
}

static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave)
{
DEFINE_COMPILER;

SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2);
SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0));

OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount));
CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave);

/* Store match begin and end. */
OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin));
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets));
OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0);
#ifdef COMPILE_PCRE16
OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
#endif
OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0);

OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0);
#ifdef COMPILE_PCRE16
OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
#endif
OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0);

JUMPTO(SLJIT_JUMP, leave);
}

static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)
{
/* May destroy TMP1. */
DEFINE_COMPILER;
struct sljit_jump *jump;

if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
  {
  /* The value of -1 must be kept for start_used_ptr! */
  OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1);
  /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
  is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
  jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
  JUMPHERE(jump);
  }
else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
  {
  jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
  JUMPHERE(jump);
  }
}

static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc)
{
/* Detects if the character has an othercase. */
unsigned int c;

#ifdef SUPPORT_UTF
if (common->utf)
  {
  GETCHAR(c, cc);
  if (c > 127)
    {
#ifdef SUPPORT_UCP
    return c != UCD_OTHERCASE(c);
#else
    return FALSE;
#endif
    }
#ifndef COMPILE_PCRE8
  return common->fcc[c] != c;
#endif
  }
else
#endif
  c = *cc;
return MAX_255(c) ? common->fcc[c] != c : FALSE;
}

static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
{
/* Returns with the othercase. */
#ifdef SUPPORT_UTF
if (common->utf && c > 127)
  {
#ifdef SUPPORT_UCP
  return UCD_OTHERCASE(c);
#else
  return c;
#endif
  }
#endif
return TABLE_GET(c, common->fcc, c);
}

static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc)
{
/* Detects if the character and its othercase has only 1 bit difference. */
unsigned int c, oc, bit;
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
int n;
#endif

#ifdef SUPPORT_UTF
if (common->utf)
  {
  GETCHAR(c, cc);
  if (c <= 127)
    oc = common->fcc[c];
  else
    {
#ifdef SUPPORT_UCP
    oc = UCD_OTHERCASE(c);
#else
    oc = c;
#endif
    }
  }
else
  {
  c = *cc;
  oc = TABLE_GET(c, common->fcc, c);
  }
#else
c = *cc;
oc = TABLE_GET(c, common->fcc, c);
#endif

SLJIT_ASSERT(c != oc);

bit = c  oc;
/* Optimized for English alphabet. */
if (c <= 127 && bit == 0x20)
  return (0 << 8) | 0x20;

/* Since c != oc, they must have at least 1 bit difference. */
if (!ispowerof2(bit))
  return 0;

#ifdef COMPILE_PCRE8

#ifdef SUPPORT_UTF
if (common->utf && c > 127)
  {
  n = GET_EXTRALEN(*cc);
  while ((bit & 0x3f) == 0)
    {
    n--;
    bit >>= 6;
    }
  return (n << 8) | bit;
  }
#endif /* SUPPORT_UTF */
return (0 << 8) | bit;

#else /* COMPILE_PCRE8 */

#ifdef COMPILE_PCRE16
#ifdef SUPPORT_UTF
if (common->utf && c > 65535)
  {
  if (bit >= (1 << 10))
    bit >>= 10;
  else
    return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
  }
#endif /* SUPPORT_UTF */
return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
#endif /* COMPILE_PCRE16 */

#endif /* COMPILE_PCRE8 */
}

static void check_partial(compiler_common *common, BOOL force)
{
/* Checks whether a partial matching is occured. Does not modify registers. */
DEFINE_COMPILER;
struct sljit_jump *jump = NULL;

SLJIT_ASSERT(!force || common->mode != JIT_COMPILE);

if (common->mode == JIT_COMPILE)
  return;

if (!force)
  jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
else if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
  jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);

if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
else
  {
  if (common->partialmatchlabel != NULL)
    JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
  else
    add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
  }

if (jump != NULL)
  JUMPHERE(jump);
}

static struct sljit_jump *check_str_end(compiler_common *common)
{
/* Does not affect registers. Usually used in a tight spot. */
DEFINE_COMPILER;
struct sljit_jump *jump;
struct sljit_jump *nohit;
struct sljit_jump *return_value;

if (common->mode == JIT_COMPILE)
  return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);

jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
  {
  nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
  JUMPHERE(nohit);
  return_value = JUMP(SLJIT_JUMP);
  }
else
  {
  return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
  if (common->partialmatchlabel != NULL)
    JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
  else
    add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
  }
JUMPHERE(jump);
return return_value;
}

static void detect_partial_match(compiler_common *common, jump_list **backtracks)
{
DEFINE_COMPILER;
struct sljit_jump *jump;

if (common->mode == JIT_COMPILE)
  {
  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
  return;
  }

/* Partial matching mode. */
jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0));
if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
  add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
  }
else
  {
  if (common->partialmatchlabel != NULL)
    JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
  else
    add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
  }
JUMPHERE(jump);
}

static void read_char(compiler_common *common)
{
/* Reads the character into TMP1, updates STR_PTR.
Does not check STR_END. TMP2 Destroyed. */
DEFINE_COMPILER;
#ifdef SUPPORT_UTF
struct sljit_jump *jump;
#endif

OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
#ifdef SUPPORT_UTF
if (common->utf)
  {
#ifdef COMPILE_PCRE8
  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
#else
#ifdef COMPILE_PCRE16
  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
#endif
#endif /* COMPILE_PCRE8 */
  add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
  JUMPHERE(jump);
  }
#endif
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}

static void peek_char(compiler_common *common)
{
/* Reads the character into TMP1, keeps STR_PTR.
Does not check STR_END. TMP2 Destroyed. */
DEFINE_COMPILER;
#ifdef SUPPORT_UTF
struct sljit_jump *jump;
#endif

OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
#ifdef SUPPORT_UTF
if (common->utf)
  {
#ifdef COMPILE_PCRE8
  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
#else
#ifdef COMPILE_PCRE16
  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
#endif
#endif /* COMPILE_PCRE8 */
  add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
  JUMPHERE(jump);
  }
#endif
}

static void read_char8_type(compiler_common *common)
{
/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
DEFINE_COMPILER;
#if defined SUPPORT_UTF || defined COMPILE_PCRE16
struct sljit_jump *jump;
#endif

#ifdef SUPPORT_UTF
if (common->utf)
  {
  OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#ifdef COMPILE_PCRE8
  /* This can be an extra read in some situations, but hopefully
  it is needed in most cases. */
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
  jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
  add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
  JUMPHERE(jump);
#else
#ifdef COMPILE_PCRE16
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
  jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
  JUMPHERE(jump);
  /* Skip low surrogate if necessary. */
  OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800);
  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
#endif
#endif /* COMPILE_PCRE8 */
  return;
  }
#endif
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#ifdef COMPILE_PCRE16
/* The ctypes array contains only 256 values. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
#ifdef COMPILE_PCRE16
JUMPHERE(jump);
#endif
}

static void skip_char_back(compiler_common *common)
{
/* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
DEFINE_COMPILER;
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
struct sljit_label *label;

if (common->utf)
  {
  label = LABEL();
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
  CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
  return;
  }
#endif
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
if (common->utf)
  {
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  /* Skip low surrogate if necessary. */
  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  return;
  }
#endif
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}

static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue)
{
/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
DEFINE_COMPILER;

if (nltype == NLTYPE_ANY)
  {
  add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
  }
else if (nltype == NLTYPE_ANYCRLF)
  {
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
  COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
  add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
  }
else
  {
  SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
  add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
  }
}

#ifdef SUPPORT_UTF

#ifdef COMPILE_PCRE8
static void do_utfreadchar(compiler_common *common)
{
/* Fast decoding a UTF-8 character. TMP1 contains the first byte
of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
DEFINE_COMPILER;
struct sljit_jump *jump;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
/* Searching for the first zero. */
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
jump = JUMP(SLJIT_C_NOT_ZERO);
/* Two byte sequence. */
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);

OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
jump = JUMP(SLJIT_C_NOT_ZERO);
/* Three byte sequence. */
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);

/* Four byte sequence. */
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

static void do_utfreadtype8(compiler_common *common)
{
/* Fast decoding a UTF-8 character type. TMP2 contains the first byte
of the character (>= 0xc0). Return value in TMP1. */
DEFINE_COMPILER;
struct sljit_jump *jump;
struct sljit_jump *compare;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);

OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
jump = JUMP(SLJIT_C_NOT_ZERO);
/* Two byte sequence. */
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);

JUMPHERE(compare);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);

/* We only have types for characters less than 256. */
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

#else /* COMPILE_PCRE8 */

#ifdef COMPILE_PCRE16
static void do_utfreadchar(compiler_common *common)
{
/* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
DEFINE_COMPILER;
struct sljit_jump *jump;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
/* Do nothing, only return. */
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);

JUMPHERE(jump);
/* Combine two 16 bit characters. */
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
#endif /* COMPILE_PCRE16 */

#endif /* COMPILE_PCRE8 */

#endif /* SUPPORT_UTF */

#ifdef SUPPORT_UCP

/* UCD_BLOCK_SIZE must be 128 (see the assert below). */
#define UCD_BLOCK_MASK 127
#define UCD_BLOCK_SHIFT 7

static void do_getucd(compiler_common *common)
{
/* Search the UCD record for the character comes in TMP1.
Returns chartype in TMP1 and UCD offset in TMP2. */
DEFINE_COMPILER;

SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_stage2));
OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
#endif

static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
{
DEFINE_COMPILER;
struct sljit_label *mainloop;
struct sljit_label *newlinelabel = NULL;
struct sljit_jump *start;
struct sljit_jump *end = NULL;
struct sljit_jump *nl = NULL;
#ifdef SUPPORT_UTF
struct sljit_jump *singlechar;
#endif
jump_list *newline = NULL;
BOOL newlinecheck = FALSE;
BOOL readuchar = FALSE;

if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
    common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
  newlinecheck = TRUE;

if (firstline)
  {
  /* Search for the end of the first line. */
  SLJIT_ASSERT(common->first_line_end != 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_END, 0);

  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
    {
    mainloop = LABEL();
    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
    end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
    CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
    OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
    }
  else
    {
    end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
    mainloop = LABEL();
    /* Continual stores does not cause data dependency. */
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
    read_char(common);
    check_newlinechar(common, common->nltype, &newline, TRUE);
    CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
    set_jumps(newline, LABEL());
    }

  JUMPHERE(end);
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
  }

start = JUMP(SLJIT_JUMP);

if (newlinecheck)
  {
  newlinelabel = LABEL();
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
#ifdef COMPILE_PCRE16
  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
#endif
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  nl = JUMP(SLJIT_JUMP);
  }

mainloop = LABEL();

/* Increasing the STR_PTR here requires one less jump in the most common case. */
#ifdef SUPPORT_UTF
if (common->utf) readuchar = TRUE;
#endif
if (newlinecheck) readuchar = TRUE;

if (readuchar)
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);

if (newlinecheck)
  CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);

OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (common->utf)
  {
  singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  JUMPHERE(singlechar);
  }
#endif
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
if (common->utf)
  {
  singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  JUMPHERE(singlechar);
  }
#endif
JUMPHERE(start);

if (newlinecheck)
  {
  JUMPHERE(end);
  JUMPHERE(nl);
  }

return mainloop;
}

static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)
{
DEFINE_COMPILER;
struct sljit_label *start;
struct sljit_jump *leave;
struct sljit_jump *found;
pcre_uchar oc, bit;

if (firstline)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
  }

start = LABEL();
leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);

oc = first_char;
if (caseless)
  {
  oc = TABLE_GET(first_char, common->fcc, first_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
  if (first_char > 127 && common->utf)
    oc = UCD_OTHERCASE(first_char);
#endif
  }
if (first_char == oc)
  found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char);
else
  {
  bit = first_char  oc;
  if (ispowerof2(bit))
    {
    OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
    found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit);
    }
  else
    {
    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char);
    COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
    COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
    found = JUMP(SLJIT_C_NOT_ZERO);
    }
  }

OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (common->utf)
  {
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  }
#endif
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
if (common->utf)
  {
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  }
#endif
JUMPTO(SLJIT_JUMP, start);
JUMPHERE(found);
JUMPHERE(leave);

if (firstline)
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
}

static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
{
DEFINE_COMPILER;
struct sljit_label *loop;
struct sljit_jump *lastchar;
struct sljit_jump *firstchar;
struct sljit_jump *leave;
struct sljit_jump *foundcr = NULL;
struct sljit_jump *notfoundnl;
jump_list *newline = NULL;

if (firstline)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
  }

if (common->nltype == NLTYPE_FIXED && common->newline > 255)
  {
  lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
  firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);

  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
#ifdef COMPILE_PCRE16
  OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
#endif
  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);

  loop = LABEL();
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
  OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
  CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
  CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);

  JUMPHERE(leave);
  JUMPHERE(firstchar);
  JUMPHERE(lastchar);

  if (firstline)
    OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
  return;
  }

OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
skip_char_back(common);

loop = LABEL();
read_char(common);
lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
  foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
check_newlinechar(common, common->nltype, &newline, FALSE);
set_jumps(newline, loop);

if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
  {
  leave = JUMP(SLJIT_JUMP);
  JUMPHERE(foundcr);
  notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
#ifdef COMPILE_PCRE16
  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
#endif
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  JUMPHERE(notfoundnl);
  JUMPHERE(leave);
  }
JUMPHERE(lastchar);
JUMPHERE(firstchar);

if (firstline)
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
}

static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
{
DEFINE_COMPILER;
struct sljit_label *start;
struct sljit_jump *leave;
struct sljit_jump *found;
#ifndef COMPILE_PCRE8
struct sljit_jump *jump;
#endif

if (firstline)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
  }

start = LABEL();
leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
#ifdef SUPPORT_UTF
if (common->utf)
  OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
#endif
#ifndef COMPILE_PCRE8
jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255);
JUMPHERE(jump);
#endif
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
found = JUMP(SLJIT_C_NOT_ZERO);

#ifdef SUPPORT_UTF
if (common->utf)
  OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
#endif
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (common->utf)
  {
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  }
#endif
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
if (common->utf)
  {
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
  }
#endif
JUMPTO(SLJIT_JUMP, start);
JUMPHERE(found);
JUMPHERE(leave);

if (firstline)
  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
}

static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar)
{
DEFINE_COMPILER;
struct sljit_label *loop;
struct sljit_jump *toolong;
struct sljit_jump *alreadyfound;
struct sljit_jump *found;
struct sljit_jump *foundoc = NULL;
struct sljit_jump *notfound;
pcre_uchar oc, bit;

SLJIT_ASSERT(common->req_char_ptr != 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr);
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);

if (has_firstchar)
  OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
else
  OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);

loop = LABEL();
notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);

OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);
oc = req_char;
if (caseless)
  {
  oc = TABLE_GET(req_char, common->fcc, req_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
  if (req_char > 127 && common->utf)
    oc = UCD_OTHERCASE(req_char);
#endif
  }
if (req_char == oc)
  found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
else
  {
  bit = req_char  oc;
  if (ispowerof2(bit))
    {
    OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
    found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);
    }
  else
    {
    found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
    foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
    }
  }
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_JUMP, loop);

JUMPHERE(found);
if (foundoc)
  JUMPHERE(foundoc);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0);
JUMPHERE(alreadyfound);
JUMPHERE(toolong);
return notfound;
}

static void do_revertframes(compiler_common *common)
{
DEFINE_COMPILER;
struct sljit_jump *jump;
struct sljit_label *mainloop;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
GET_LOCAL_BASE(TMP3, 0, 0);

/* Drop frames until we reach STACK_TOP. */
mainloop = LABEL();
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
JUMPTO(SLJIT_JUMP, mainloop);

JUMPHERE(jump);
jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
/* End of dropping frames. */
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);

JUMPHERE(jump);
jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
/* Set string begin. */
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
JUMPTO(SLJIT_JUMP, mainloop);

JUMPHERE(jump);
if (common->mark_ptr != 0)
  {
  jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmark);
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
  JUMPTO(SLJIT_JUMP, mainloop);

  JUMPHERE(jump);
  }

/* Unknown command. */
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
JUMPTO(SLJIT_JUMP, mainloop);
}

static void check_wordboundary(compiler_common *common)
{
DEFINE_COMPILER;
struct sljit_jump *skipread;
#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
struct sljit_jump *jump;
#endif

SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);

sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
/* Get type of the previous char, and put it to LOCALS1. */
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
skip_char_back(common);
check_start_used_ptr(common);
read_char(common);

/* Testing char type. */
#ifdef SUPPORT_UCP
if (common->use_ucp)
  {
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
  jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
  JUMPHERE(jump);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
  }
else
#endif
  {
#ifndef COMPILE_PCRE8
  jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
#elif defined SUPPORT_UTF
  /* Here LOCALS1 has already been zeroed. */
  jump = NULL;
  if (common->utf)
    jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
#endif /* COMPILE_PCRE8 */
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
  OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
  OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
#ifndef COMPILE_PCRE8
  JUMPHERE(jump);
#elif defined SUPPORT_UTF
  if (jump != NULL)
    JUMPHERE(jump);
#endif /* COMPILE_PCRE8 */
  }
JUMPHERE(skipread);

OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
skipread = check_str_end(common);
peek_char(common);

/* Testing char type. This is a code duplication. */
#ifdef SUPPORT_UCP
if (common->use_ucp)
  {
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
  jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
  JUMPHERE(jump);
  }
else
#endif
  {
#ifndef COMPILE_PCRE8
  /* TMP2 may be destroyed by peek_char. */
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
  jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
#elif defined SUPPORT_UTF
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
  jump = NULL;
  if (common->utf)
    jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
#endif
  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
  OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
  OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
#ifndef COMPILE_PCRE8
  JUMPHERE(jump);
#elif defined SUPPORT_UTF
  if (jump != NULL)
    JUMPHERE(jump);
#endif /* COMPILE_PCRE8 */
  }
JUMPHERE(skipread);

OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
}

static void check_anynewline(compiler_common *common)
{
/* Check whether TMP1 contains a newline character. TMP2 destroyed. */
DEFINE_COMPILER;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);

OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16
#ifdef COMPILE_PCRE8
if (common->utf)
  {
#endif
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
#ifdef COMPILE_PCRE8
  }
#endif
#endif /* SUPPORT_UTF || COMPILE_PCRE16 */
COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

static void check_hspace(compiler_common *common)
{
/* Check whether TMP1 contains a newline character. TMP2 destroyed. */
DEFINE_COMPILER;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);

OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16
#ifdef COMPILE_PCRE8
if (common->utf)
  {
#endif
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
  OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
#ifdef COMPILE_PCRE8
  }
#endif
#endif /* SUPPORT_UTF || COMPILE_PCRE16 */
COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);

sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

static void check_vspace(compiler_common *common)
{
/* Check whether TMP1 contains a newline character. TMP2 destroyed. */
DEFINE_COMPILER;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);

OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
#if defined SUPPORT_UTF || defined COMPILE_PCRE16
#ifdef COMPILE_PCRE8
if (common->utf)
  {
#endif
  COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
#ifdef COMPILE_PCRE8
  }
#endif
#endif /* SUPPORT_UTF || COMPILE_PCRE16 */
COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);

sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

#define CHAR1 STR_END
#define CHAR2 STACK_TOP

static void do_casefulcmp(compiler_common *common)
{
DEFINE_COMPILER;
struct sljit_jump *jump;
struct sljit_label *label;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));

label = LABEL();
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_C_NOT_ZERO, label);

JUMPHERE(jump);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

#define LCC_TABLE STACK_LIMIT

static void do_caselesscmp(compiler_common *common)
{
DEFINE_COMPILER;
struct sljit_jump *jump;
struct sljit_label *label;

sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);

OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));

label = LABEL();
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
#ifndef COMPILE_PCRE8
jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
#ifndef COMPILE_PCRE8
JUMPHERE(jump);
jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
#ifndef COMPILE_PCRE8
JUMPHERE(jump);
#endif
jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_C_NOT_ZERO, label);

JUMPHERE(jump);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}

#undef LCC_TABLE
#undef CHAR1
#undef CHAR2

#if defined SUPPORT_UTF && defined SUPPORT_UCP

static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1)
{
/* This function would be ineffective to do in JIT level. */
int c1, c2;
const pcre_uchar *src2 = args->uchar_ptr;
const pcre_uchar *end2 = args->end;

while (src1 < end1)
  {
  if (src2 >= end2)
    return (pcre_uchar*)1;
  GETCHARINC(c1, src1);
  GETCHARINC(c2, src2);
  if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return NULL;
  }
return src2;
}

#endif /* SUPPORT_UTF && SUPPORT_UCP */

static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
    compare_context* context, jump_list **backtracks)
{
DEFINE_COMPILER;
unsigned int othercasebit = 0;
pcre_uchar *othercasechar = NULL;
#ifdef SUPPORT_UTF
int utflength;
#endif

if (caseless && char_has_othercase(common, cc))
  {
  othercasebit = char_get_othercase_bit(common, cc);
  SLJIT_ASSERT(othercasebit);
  /* Extracting bit difference info. */
#ifdef COMPILE_PCRE8
  othercasechar = cc + (othercasebit >> 8);
  othercasebit &= 0xff;
#else
#ifdef COMPILE_PCRE16
  othercasechar = cc + (othercasebit >> 9);
  if ((othercasebit & 0x100) != 0)
    othercasebit = (othercasebit & 0xff) << 8;
  else
    othercasebit &= 0xff;
#endif
#endif
  }

if (context->sourcereg == -1)
  {
#ifdef COMPILE_PCRE8
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
  if (context->length >= 4)
    OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
  else if (context->length >= 2)
    OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
  else
#endif
    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
#else
#ifdef COMPILE_PCRE16
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
  if (context->length >= 4)
    OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
  else
#endif
    OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
#endif
#endif /* COMPILE_PCRE8 */
  context->sourcereg = TMP2;
  }

#ifdef SUPPORT_UTF
utflength = 1;
if (common->utf && HAS_EXTRALEN(*cc))
  utflength += GET_EXTRALEN(*cc);

do
  {
#endif

  context->length -= IN_UCHARS(1);
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED

  /* Unaligned read is supported. */
  if (othercasebit != 0 && othercasechar == cc)
    {
    context->c.asuchars[context->ucharptr] = *cc | othercasebit;
    context->oc.asuchars[context->ucharptr] = othercasebit;
    }
  else
    {
    context->c.asuchars[context->ucharptr] = *cc;
    context->oc.asuchars[context->ucharptr] = 0;
    }
  context->ucharptr++;

#ifdef COMPILE_PCRE8
  if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))
#else
  if (context->ucharptr >= 2 || context->length == 0)
#endif
    {
    if (context->length >= 4)
      OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
#ifdef COMPILE_PCRE8
    else if (context->length >= 2)
      OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
    else if (context->length >= 1)
      OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
#else
    else if (context->length >= 2)
      OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
#endif
    context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;

    switch(context->ucharptr)
      {
      case 4 / sizeof(pcre_uchar):
      if (context->oc.asint != 0)
        OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
      break;

      case 2 / sizeof(pcre_uchar):
      if (context->oc.asushort != 0)
        OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
      break;

#ifdef COMPILE_PCRE8
      case 1:
      if (context->oc.asbyte != 0)
        OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
      break;
#endif

      default:
      SLJIT_ASSERT_STOP();
      break;
      }
    context->ucharptr = 0;
    }

#else

  /* Unaligned read is unsupported. */
#ifdef COMPILE_PCRE8
  if (context->length > 0)
    OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
#else
  if (context->length > 0)
    OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
#endif
  context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;

  if (othercasebit != 0 && othercasechar == cc)
    {
    OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
    }
  else
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));

#endif

  cc++;
#ifdef SUPPORT_UTF
  utflength--;
  }
while (utflength > 0);
#endif

return cc;
}

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8

#define SET_TYPE_OFFSET(value) \
  if ((value) != typeoffset) \
    { \
    if ((value) > typeoffset) \
      OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
    else \
      OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
    } \
  typeoffset = (value);

#define SET_CHAR_OFFSET(value) \
  if ((value) != charoffset) \
    { \
    if ((value) > charoffset) \
      OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
    else \
      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
    } \
  charoffset = (value);

static void compile_xclass_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
{
DEFINE_COMPILER;
jump_list *found = NULL;
jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks;
unsigned int c;
int compares;
struct sljit_jump *jump = NULL;
pcre_uchar *ccbegin;
#ifdef SUPPORT_UCP
BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
BOOL charsaved = FALSE;
int typereg = TMP1, scriptreg = TMP1;
unsigned int typeoffset;
#endif
int invertcmp, numberofcmps;
unsigned int charoffset;

/* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
detect_partial_match(common, backtracks);
read_char(common);

if ((*cc++ & XCL_MAP) != 0)
  {
  OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
#ifndef COMPILE_PCRE8
  jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
#elif defined SUPPORT_UTF
  if (common->utf)
    jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
#endif

  OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
  OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
  OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
  add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));

#ifndef COMPILE_PCRE8
  JUMPHERE(jump);
#elif defined SUPPORT_UTF
  if (common->utf)
    JUMPHERE(jump);
#endif
  OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
#ifdef SUPPORT_UCP
  charsaved = TRUE;
#endif
  cc += 32 / sizeof(pcre_uchar);
  }

/* Scanning the necessary info. */
ccbegin = cc;
compares = 0;
while (*cc != XCL_END)
  {
  compares++;
  if (*cc == XCL_SINGLE)
    {
    cc += 2;
#ifdef SUPPORT_UTF
    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
#ifdef SUPPORT_UCP
    needschar = TRUE;
#endif
    }
  else if (*cc == XCL_RANGE)
    {
    cc += 2;
#ifdef SUPPORT_UTF
    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
    cc++;
#ifdef SUPPORT_UTF
    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
#ifdef SUPPORT_UCP
    needschar = TRUE;
#endif
    }
#ifdef SUPPORT_UCP
  else
    {
    SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
    cc++;
    switch(*cc)
      {
      case PT_ANY:
      break;

      case PT_LAMP:
      case PT_GC:
      case PT_PC:
      case PT_ALNUM:
      needstype = TRUE;
      break;

      case PT_SC:
      needsscript = TRUE;
      break;

      case PT_SPACE:
      case PT_PXSPACE:
      case PT_WORD:
      needstype = TRUE;
      needschar = TRUE;
      break;

      default:
      SLJIT_ASSERT_STOP();
      break;
      }
    cc += 2;
    }
#endif
  }

#ifdef SUPPORT_UCP
/* Simple register allocation. TMP1 is preferred if possible. */
if (needstype || needsscript)
  {
  if (needschar && !charsaved)
    OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
  if (needschar)
    {
    if (needstype)
      {
      OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
      typereg = RETURN_ADDR;
      }

    if (needsscript)
      scriptreg = TMP3;
    OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
    }
  else if (needstype && needsscript)
    scriptreg = TMP3;
  /* In all other cases only one of them was specified, and that can goes to TMP1. */

  if (needsscript)
    {
    if (scriptreg == TMP1)
      {
      OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
      OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
      }
    else
      {
      OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
      OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
      OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
      }
    }
  }
#endif

/* Generating code. */
cc = ccbegin;
charoffset = 0;
numberofcmps = 0;
#ifdef SUPPORT_UCP
typeoffset = 0;
#endif

while (*cc != XCL_END)
  {
  compares--;
  invertcmp = (compares == 0 && list != backtracks);
  jump = NULL;

  if (*cc == XCL_SINGLE)
    {
    cc ++;
#ifdef SUPPORT_UTF
    if (common->utf)
      {
      GETCHARINC(c, cc);
      }
    else
#endif
      c = *cc++;

    if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
      {
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
      COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
      numberofcmps++;
      }
    else if (numberofcmps > 0)
      {
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
      jump = JUMP(SLJIT_C_NOT_ZERO  invertcmp);
      numberofcmps = 0;
      }
    else
      {
      jump = CMP(SLJIT_C_EQUAL  invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
      numberofcmps = 0;
      }
    }
  else if (*cc == XCL_RANGE)
    {
    cc ++;
#ifdef SUPPORT_UTF
    if (common->utf)
      {
      GETCHARINC(c, cc);
      }
    else
#endif
      c = *cc++;
    SET_CHAR_OFFSET(c);
#ifdef SUPPORT_UTF
    if (common->utf)
      {
      GETCHARINC(c, cc);
      }
    else
#endif
      c = *cc++;
    if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
      {
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
      COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
      numberofcmps++;
      }
    else if (numberofcmps > 0)
      {
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
      jump = JUMP(SLJIT_C_NOT_ZERO  invertcmp);
      numberofcmps = 0;
      }
    else
      {
      jump = CMP(SLJIT_C_LESS_EQUAL  invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
      numberofcmps = 0;
      }
    }
#ifdef SUPPORT_UCP
  else
    {
    if (*cc == XCL_NOTPROP)
      invertcmp = 0x1;
    cc++;
    switch(*cc)
      {
      case PT_ANY:
      if (list != backtracks)
        {
        if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
          continue;
        }
      else if (cc[-1] == XCL_NOTPROP)
        continue;
      jump = JUMP(SLJIT_JUMP);
      break;

      case PT_LAMP:
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
      COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
      jump = JUMP(SLJIT_C_NOT_ZERO  invertcmp);
      break;

      case PT_GC:
      c = PRIV(ucp_typerange)[(int)cc[1] * 2];
      SET_TYPE_OFFSET(c);
      jump = CMP(SLJIT_C_LESS_EQUAL  invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);
      break;

      case PT_PC:
      jump = CMP(SLJIT_C_EQUAL  invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
      break;

      case PT_SC:
      jump = CMP(SLJIT_C_EQUAL  invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
      break;

      case PT_SPACE:
      case PT_PXSPACE:
      if (*cc == PT_SPACE)
        {
        OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
        jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
        }
      SET_CHAR_OFFSET(9);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
      if (*cc == PT_SPACE)
        JUMPHERE(jump);

      SET_TYPE_OFFSET(ucp_Zl);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
      jump = JUMP(SLJIT_C_NOT_ZERO  invertcmp);
      break;

      case PT_WORD:
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
      /* ... fall through */

      case PT_ALNUM:
      SET_TYPE_OFFSET(ucp_Ll);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
      COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
      SET_TYPE_OFFSET(ucp_Nd);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
      jump = JUMP(SLJIT_C_NOT_ZERO  invertcmp);
      break;
      }
    cc += 2;
    }
#endif

  if (jump != NULL)
    add_jump(compiler, compares > 0 ? list : backtracks, jump);
  }

if (found != NULL)
  set_jumps(found, LABEL());
}

#undef SET_TYPE_OFFSET
#undef SET_CHAR_OFFSET

#endif

static pcre_uchar *compile_char1_trypath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
{
DEFINE_COMPILER;
int length;
unsigned int c, oc, bit;
compare_context context;
struct sljit_jump *jump[4];
#ifdef SUPPORT_UTF
struct sljit_label *label;
#ifdef SUPPORT_UCP
pcre_uchar propdata[5];
#endif
#endif

switch(type)
  {
  case OP_SOD:
  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
  return cc;

  case OP_SOM:
  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
  return cc;

  case OP_NOT_WORD_BOUNDARY:
  case OP_WORD_BOUNDARY:
  add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
  return cc;

  case OP_NOT_DIGIT:
  case OP_DIGIT:
  detect_partial_match(common, backtracks);
  read_char8_type(common);
  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
  add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
  return cc;

  case OP_NOT_WHITESPACE:
  case OP_WHITESPACE:
  detect_partial_match(common, backtracks);
  read_char8_type(common);
  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
  add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
  return cc;

  case OP_NOT_WORDCHAR:
  case OP_WORDCHAR:
  detect_partial_match(common, backtracks);
  read_char8_type(common);
  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
  add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
  return cc;

  case OP_ANY:
  detect_partial_match(common, backtracks);
  read_char(common);
  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
    {
    jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
    if (common->mode != JIT_PARTIAL_HARD_COMPILE)
      jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
    else
      jump[1] = check_str_end(common);

    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
    add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
    if (jump[1] != NULL)
      JUMPHERE(jump[1]);
    JUMPHERE(jump[0]);
    }
  else
    check_newlinechar(common, common->nltype, backtracks, TRUE);
  return cc;

  case OP_ALLANY:
  detect_partial_match(common, backtracks);
#ifdef SUPPORT_UTF
  if (common->utf)
    {
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#ifdef COMPILE_PCRE8
    jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
#else /* COMPILE_PCRE8 */
#ifdef COMPILE_PCRE16
    jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
    OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
    COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
    OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
#endif /* COMPILE_PCRE16 */
#endif /* COMPILE_PCRE8 */
    JUMPHERE(jump[0]);
    return cc;
    }
#endif
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  return cc;

  case OP_ANYBYTE:
  detect_partial_match(common, backtracks);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  return cc;

#ifdef SUPPORT_UTF
#ifdef SUPPORT_UCP
  case OP_NOTPROP:
  case OP_PROP:
  propdata[0] = 0;
  propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
  propdata[2] = cc[0];
  propdata[3] = cc[1];
  propdata[4] = XCL_END;
  compile_xclass_trypath(common, propdata, backtracks);
  return cc + 2;
#endif
#endif

  case OP_ANYNL:
  detect_partial_match(common, backtracks);
  read_char(common);
  jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
  /* We don't need to handle soft partial matching case. */
  if (common->mode != JIT_PARTIAL_HARD_COMPILE)
    jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  else
    jump[1] = check_str_end(common);
  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
  jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
  jump[3] = JUMP(SLJIT_JUMP);
  JUMPHERE(jump[0]);
  check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
  JUMPHERE(jump[1]);
  JUMPHERE(jump[2]);
  JUMPHERE(jump[3]);
  return cc;

  case OP_NOT_HSPACE:
  case OP_HSPACE:
  detect_partial_match(common, backtracks);
  read_char(common);
  add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
  return cc;

  case OP_NOT_VSPACE:
  case OP_VSPACE:
  detect_partial_match(common, backtracks);
  read_char(common);
  add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
  return cc;

#ifdef SUPPORT_UCP
  case OP_EXTUNI:
  detect_partial_match(common, backtracks);
  read_char(common);
  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
  add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));

  label = LABEL();
  jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
  read_char(common);
  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
  CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);

  OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
  JUMPHERE(jump[0]);
  if (common->mode == JIT_PARTIAL_HARD_COMPILE)
    {
    jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
    /* Since we successfully read a char above, partial matching must occure. */
    check_partial(common, TRUE);
    JUMPHERE(jump[0]);
    }
  return cc;
#endif

  case OP_EODN:
  /* Requires rather complex checks. */
  jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
    {
    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    if (common->mode == JIT_COMPILE)
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
    else
      {
      jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS);
      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL);
      add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL));
      check_partial(common, TRUE);
      add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
      JUMPHERE(jump[1]);
      }
    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
    }
  else if (common->nltype == NLTYPE_FIXED)
    {
    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
    }
  else
    {
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
    OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
    jump[2] = JUMP(SLJIT_C_GREATER);
    add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS));
    /* Equal. */
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
    jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
    add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));

    JUMPHERE(jump[1]);
    if (common->nltype == NLTYPE_ANYCRLF)
      {
      OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
      add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
      }
    else
      {
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
      read_char(common);
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
      add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
      add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
      }
    JUMPHERE(jump[2]);
    JUMPHERE(jump[3]);
    }
  JUMPHERE(jump[0]);
  check_partial(common, FALSE);
  return cc;

  case OP_EOD:
  add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
  check_partial(common, FALSE);
  return cc;

  case OP_CIRC:
  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
  return cc;

  case OP_CIRCM:
  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
  jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
  jump[0] = JUMP(SLJIT_JUMP);
  JUMPHERE(jump[1]);

  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
    {
    OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
    }
  else
    {
    skip_char_back(common);
    read_char(common);
    check_newlinechar(common, common->nltype, backtracks, FALSE);
    }
  JUMPHERE(jump[0]);
  return cc;

  case OP_DOLL:
  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));

  if (!common->endonly)
    compile_char1_trypath(common, OP_EODN, cc, backtracks);
  else
    {
    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
    check_partial(common, FALSE);
    }
  return cc;

  case OP_DOLLM:
  jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
  check_partial(common, FALSE);
  jump[0] = JUMP(SLJIT_JUMP);
  JUMPHERE(jump[1]);

  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
    {
    OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
    if (common->mode == JIT_COMPILE)
      add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
    else
      {
      jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0);
      /* STR_PTR = STR_END - IN_UCHARS(1) */
      add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
      check_partial(common, TRUE);
      add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
      JUMPHERE(jump[1]);
      }

    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
    }
  else
    {
    peek_char(common);
    check_newlinechar(common, common->nltype, backtracks, FALSE);
    }
  JUMPHERE(jump[0]);
  return cc;

  case OP_CHAR:
  case OP_CHARI:
  length = 1;
#ifdef SUPPORT_UTF
  if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
#endif
  if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
    {
    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
    add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));

    context.length = IN_UCHARS(length);
    context.sourcereg = -1;
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
    context.ucharptr = 0;
#endif
    return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
    }
  detect_partial_match(common, backtracks);
  read_char(common);
#ifdef SUPPORT_UTF
  if (common->utf)
    {
    GETCHAR(c, cc);
    }
  else
#endif
    c = *cc;
  if (type == OP_CHAR || !char_has_othercase(common, cc))
    {
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
    return cc + length;
    }
  oc = char_othercase(common, c);
  bit = c  oc;
  if (ispowerof2(bit))
    {
    OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
    return cc + length;
    }
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
  COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
  add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
  return cc + length;

  case OP_NOT:
  case OP_NOTI:
  detect_partial_match(common, backtracks);
  length = 1;
#ifdef SUPPORT_UTF
  if (common->utf)
    {
#ifdef COMPILE_PCRE8
    c = *cc;
    if (c < 128)
      {
      OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
      if (type == OP_NOT || !char_has_othercase(common, cc))
        add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
      else
        {
        /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
        OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);
        add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));
        }
      /* Skip the variable-length character. */
      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
      jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
      OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
      OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
      JUMPHERE(jump[0]);
      return cc + 1;
      }
    else
#endif /* COMPILE_PCRE8 */
      {
      GETCHARLEN(c, cc, length);
      read_char(common);
      }
    }
  else
#endif /* SUPPORT_UTF */
    {
    read_char(common);
    c = *cc;
    }

  if (type == OP_NOT || !char_has_othercase(common, cc))
    add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
  else
    {
    oc = char_othercase(common, c);
    bit = c  oc;
    if (ispowerof2(bit))
      {
      OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
      }
    else
      {
      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
      add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
      }
    }
  return cc + length;

  case OP_CLASS:
  case OP_NCLASS:
  detect_partial_match(common, backtracks);
  read_char(common);
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
  jump[0] = NULL;
#ifdef COMPILE_PCRE8
  /* This check only affects 8 bit mode. In other modes, we
  always need to compare the value with 255. */
  if (common->utf)
#endif /* COMPILE_PCRE8 */
    {
    jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
    if (type == OP_CLASS)
      {
      add_jump(compiler, backtracks, jump[0]);
      jump[0] = NULL;
      }
    }
#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
  OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
  OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
  OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
  add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
  if (jump[0] != NULL)
    JUMPHERE(jump[0]);
#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
  return cc + 32 / sizeof(pcre_uchar);

#if defined SUPPORT_UTF || defined COMPILE_PCRE16
  case OP_XCLASS:
  compile_xclass_trypath(common, cc + LINK_SIZE, backtracks);
  return cc + GET(cc, 0) - 1;
#endif

  case OP_REVERSE:
  length = GET(cc, 0);
  if (length == 0)
    return cc + LINK_SIZE;
  OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
#ifdef SUPPORT_UTF
  if (common->utf)
    {
    OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
    label = LABEL();
    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
    skip_char_back(common);
    OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
    JUMPTO(SLJIT_C_NOT_ZERO, label);
    }
  else
#endif
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
    OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
    }
  check_start_used_ptr(common);
  return cc + LINK_SIZE;
  }
SLJIT_ASSERT_STOP();
return cc;
}

static SLJIT_INLINE pcre_uchar *compile_charn_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks)
{
/* This function consumes at least one input character. */
/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
DEFINE_COMPILER;
pcre_uchar *ccbegin = cc;
compare_context context;
int size;

context.length = 0;
do
  {
  if (cc >= ccend)
    break;

  if (*cc == OP_CHAR)
    {
    size = 1;
#ifdef SUPPORT_UTF
    if (common->utf && HAS_EXTRALEN(cc[1]))
      size += GET_EXTRALEN(cc[1]);
#endif
    }
  else if (*cc == OP_CHARI)
    {
    size = 1;
#ifdef SUPPORT_UTF
    if (common->utf)
      {
      if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
        size = 0;
      else if (HAS_EXTRALEN(cc[1]))
        size += GET_EXTRALEN(cc[1]);
      }
    else
#endif
    if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
      size = 0;
    }
  else
    size = 0;

  cc += 1 + size;
  context.length += IN_UCHARS(size);
  }
while (size > 0 && context.length <= 128);

cc = ccbegin;
if (context.length > 0)
  {
  /* We have a fixed-length byte sequence. */
  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
  add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));

  context.sourcereg = -1;
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
  context.ucharptr = 0;
#endif
  do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);
  return cc;
  }

/* A non-fixed length character will be checked if length == 0. */
return compile_char1_trypath(common, *cc, cc + 1, backtracks);
}

static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
{
DEFINE_COMPILER;
int offset = GET2(cc, 1) << 1;

OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
if (!common->jscript_compat)
  {
  if (backtracks == NULL)
    {
    /* OVECTOR(1) contains the "string begin - 1" constant. */
    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
    COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
    COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
    return JUMP(SLJIT_C_NOT_ZERO);
    }
  add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
  }
return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
}

/* Forward definitions. */
static void compile_trypath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
static void compile_backtrackpath(compiler_common *, struct backtrack_common *);

#define PUSH_BACKTRACK(size, ccstart, error) \
  do \
    { \
    backtrack = sljit_alloc_memory(compiler, (size)); \
    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
      return error; \
    memset(backtrack, 0, size); \
    backtrack->prev = parent->top; \
    backtrack->cc = (ccstart); \
    parent->top = backtrack; \
    } \
  while (0)

#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
  do \
    { \
    backtrack = sljit_alloc_memory(compiler, (size)); \
    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
      return; \
    memset(backtrack, 0, size); \
    backtrack->prev = parent->top; \
    backtrack->cc = (ccstart); \
    parent->top = backtrack; \
    } \
  while (0)

#define BACKTRACK_AS(type) ((type *)backtrack)

static pcre_uchar *compile_ref_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
{
DEFINE_COMPILER;
int offset = GET2(cc, 1) << 1;
struct sljit_jump *jump = NULL;
struct sljit_jump *partial;
struct sljit_jump *nopartial;

OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
/* OVECTOR(1) contains the "string begin - 1" constant. */
if (withchecks && !common->jscript_compat)
  add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));

#if defined SUPPORT_UTF && defined SUPPORT_UCP
if (common->utf && *cc == OP_REFI)
  {
  SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
  if (withchecks)
    jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);

  /* Needed to save important temporary registers. */
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0);
  sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
  if (common->mode == JIT_COMPILE)
    add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
  else
    {
    add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
    nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
    check_partial(common, FALSE);
    add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
    JUMPHERE(nopartial);
    }
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
  }
else
#endif /* SUPPORT_UTF && SUPPORT_UCP */
  {
  OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
  if (withchecks)
    jump = JUMP(SLJIT_C_ZERO);

  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
  partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0);
  if (common->mode == JIT_COMPILE)
    add_jump(compiler, backtracks, partial);

  add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
  add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));

  if (common->mode != JIT_COMPILE)
    {
    nopartial = JUMP(SLJIT_JUMP);
    JUMPHERE(partial);
    /* TMP2 -= STR_END - STR_PTR */
    OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);
    OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);
    partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0);
    OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
    add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
    add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
    JUMPHERE(partial);
    check_partial(common, FALSE);
    add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
    JUMPHERE(nopartial);
    }
  }

if (jump != NULL)
  {
  if (emptyfail)
    add_jump(compiler, backtracks, jump);
  else
    JUMPHERE(jump);
  }
return cc + 1 + IMM2_SIZE;
}

static SLJIT_INLINE pcre_uchar *compile_ref_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
pcre_uchar type;
struct sljit_label *label;
struct sljit_jump *zerolength;
struct sljit_jump *jump = NULL;
pcre_uchar *ccbegin = cc;
int min = 0, max = 0;
BOOL minimize;

PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);

type = cc[1 + IMM2_SIZE];
minimize = (type & 0x1) != 0;
switch(type)
  {
  case OP_CRSTAR:
  case OP_CRMINSTAR:
  min = 0;
  max = 0;
  cc += 1 + IMM2_SIZE + 1;
  break;
  case OP_CRPLUS:
  case OP_CRMINPLUS:
  min = 1;
  max = 0;
  cc += 1 + IMM2_SIZE + 1;
  break;
  case OP_CRQUERY:
  case OP_CRMINQUERY:
  min = 0;
  max = 1;
  cc += 1 + IMM2_SIZE + 1;
  break;
  case OP_CRRANGE:
  case OP_CRMINRANGE:
  min = GET2(cc, 1 + IMM2_SIZE + 1);
  max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);
  cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
  break;
  default:
  SLJIT_ASSERT_STOP();
  break;
  }

if (!minimize)
  {
  if (min == 0)
    {
    allocate_stack(common, 2);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
    /* Temporary release of STR_PTR. */
    OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
    zerolength = compile_ref_checks(common, ccbegin, NULL);
    /* Restore if not zero length. */
    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
    }
  else
    {
    allocate_stack(common, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);
    }

  if (min > 1 || max > 1)
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);

  label = LABEL();
  compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);

  if (min > 1 || max > 1)
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
    OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
    if (min > 1)
      CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
    if (max > 1)
      {
      jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
      allocate_stack(common, 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      JUMPTO(SLJIT_JUMP, label);
      JUMPHERE(jump);
      }
    }

  if (max == 0)
    {
    /* Includes min > 1 case as well. */
    allocate_stack(common, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    JUMPTO(SLJIT_JUMP, label);
    }

  JUMPHERE(zerolength);
  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();

  decrease_call_count(common);
  return cc;
  }

allocate_stack(common, 2);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
if (type != OP_CRMINSTAR)
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);

if (min == 0)
  {
  zerolength = compile_ref_checks(common, ccbegin, NULL);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  jump = JUMP(SLJIT_JUMP);
  }
else
  zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks);

BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
if (max > 0)
  add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));

compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);

if (min > 1)
  {
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->trypath);
  }
else if (max > 0)
  OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);

if (jump != NULL)
  JUMPHERE(jump);
JUMPHERE(zerolength);

decrease_call_count(common);
return cc;
}

static SLJIT_INLINE pcre_uchar *compile_recurse_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
recurse_entry *entry = common->entries;
recurse_entry *prev = NULL;
int start = GET(cc, 1);

PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
while (entry != NULL)
  {
  if (entry->start == start)
    break;
  prev = entry;
  entry = entry->next;
  }

if (entry == NULL)
  {
  entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    return NULL;
  entry->next = NULL;
  entry->entry = NULL;
  entry->calls = NULL;
  entry->start = start;

  if (prev != NULL)
    prev->next = entry;
  else
    common->entries = entry;
  }

if (common->has_set_som && common->mark_ptr != 0)
  {
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
  allocate_stack(common, 2);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
  }
else if (common->has_set_som || common->mark_ptr != 0)
  {
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr);
  allocate_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
  }

if (entry->entry == NULL)
  add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
else
  JUMPTO(SLJIT_FAST_CALL, entry->entry);
/* Leave if the match is failed. */
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
return cc + 1 + LINK_SIZE;
}

static pcre_uchar *compile_assert_trypath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
{
DEFINE_COMPILER;
int framesize;
int localptr;
backtrack_common altbacktrack;
pcre_uchar *ccbegin;
pcre_uchar opcode;
pcre_uchar bra = OP_BRA;
jump_list *tmp = NULL;
jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
jump_list **found;
/* Saving previous accept variables. */
struct sljit_label *save_leavelabel = common->leavelabel;
struct sljit_label *save_acceptlabel = common->acceptlabel;
jump_list *save_leave = common->leave;
jump_list *save_accept = common->accept;
struct sljit_jump *jump;
struct sljit_jump *brajump = NULL;

if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
  {
  SLJIT_ASSERT(!conditional);
  bra = *cc;
  cc++;
  }
localptr = PRIV_DATA(cc);
SLJIT_ASSERT(localptr != 0);
framesize = get_framesize(common, cc, FALSE);
backtrack->framesize = framesize;
backtrack->localptr = localptr;
opcode = *cc;
SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
ccbegin = cc;
cc += GET(cc, 1);

if (bra == OP_BRAMINZERO)
  {
  /* This is a braminzero backtrack path. */
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  free_stack(common, 1);
  brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
  }

if (framesize < 0)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
  allocate_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  }
else
  {
  allocate_stack(common, framesize + 2);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
  OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
  init_frame(common, ccbegin, framesize + 1, 2, FALSE);
  }

memset(&altbacktrack, 0, sizeof(backtrack_common));
common->leavelabel = NULL;
common->leave = NULL;
while (1)
  {
  common->acceptlabel = NULL;
  common->accept = NULL;
  altbacktrack.top = NULL;
  altbacktrack.topbacktracks = NULL;

  if (*ccbegin == OP_ALT)
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));

  altbacktrack.cc = ccbegin;
  compile_trypath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    {
    common->leavelabel = save_leavelabel;
    common->acceptlabel = save_acceptlabel;
    common->leave = save_leave;
    common->accept = save_accept;
    return NULL;
    }
  common->acceptlabel = LABEL();
  if (common->accept != NULL)
    set_jumps(common->accept, common->acceptlabel);

  /* Reset stack. */
  if (framesize < 0)
    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
  else {
    if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
      {
      /* We don't need to keep the STR_PTR, only the previous localptr. */
      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
      }
    else
      {
      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
      }
  }

  if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
    {
    /* We know that STR_PTR was stored on the top of the stack. */
    if (conditional)
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
    else if (bra == OP_BRAZERO)
      {
      if (framesize < 0)
        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
      else
        {
        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
        }
      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      }
    else if (framesize >= 0)
      {
      /* For OP_BRA and OP_BRAMINZERO. */
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
      }
    }
  add_jump(compiler, found, JUMP(SLJIT_JUMP));

  compile_backtrackpath(common, altbacktrack.top);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    {
    common->leavelabel = save_leavelabel;
    common->acceptlabel = save_acceptlabel;
    common->leave = save_leave;
    common->accept = save_accept;
    return NULL;
    }
  set_jumps(altbacktrack.topbacktracks, LABEL());

  if (*cc != OP_ALT)
    break;

  ccbegin = cc;
  cc += GET(cc, 1);
  }
/* None of them matched. */
if (common->leave != NULL)
  set_jumps(common->leave, LABEL());

if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
  {
  /* Assert is failed. */
  if (conditional || bra == OP_BRAZERO)
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));

  if (framesize < 0)
    {
    /* The topmost item should be 0. */
    if (bra == OP_BRAZERO)
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    else
      free_stack(common, 1);
    }
  else
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    /* The topmost item should be 0. */
    if (bra == OP_BRAZERO)
      {
      free_stack(common, framesize + 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      }
    else
      free_stack(common, framesize + 2);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
    }
  jump = JUMP(SLJIT_JUMP);
  if (bra != OP_BRAZERO)
    add_jump(compiler, target, jump);

  /* Assert is successful. */
  set_jumps(tmp, LABEL());
  if (framesize < 0)
    {
    /* We know that STR_PTR was stored on the top of the stack. */
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
    /* Keep the STR_PTR on the top of the stack. */
    if (bra == OP_BRAZERO)
      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
    else if (bra == OP_BRAMINZERO)
      {
      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      }
    }
  else
    {
    if (bra == OP_BRA)
      {
      /* We don't need to keep the STR_PTR, only the previous localptr. */
      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
      }
    else
      {
      /* We don't need to keep the STR_PTR, only the previous localptr. */
      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w));
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);
      }
    }

  if (bra == OP_BRAZERO)
    {
    backtrack->trypath = LABEL();
    sljit_set_label(jump, backtrack->trypath);
    }
  else if (bra == OP_BRAMINZERO)
    {
    JUMPTO(SLJIT_JUMP, backtrack->trypath);
    JUMPHERE(brajump);
    if (framesize >= 0)
      {
      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
      }
    set_jumps(backtrack->common.topbacktracks, LABEL());
    }
  }
else
  {
  /* AssertNot is successful. */
  if (framesize < 0)
    {
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    if (bra != OP_BRA)
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    else
      free_stack(common, 1);
    }
  else
    {
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    /* The topmost item should be 0. */
    if (bra != OP_BRA)
      {
      free_stack(common, framesize + 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      }
    else
      free_stack(common, framesize + 2);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
    }

  if (bra == OP_BRAZERO)
    backtrack->trypath = LABEL();
  else if (bra == OP_BRAMINZERO)
    {
    JUMPTO(SLJIT_JUMP, backtrack->trypath);
    JUMPHERE(brajump);
    }

  if (bra != OP_BRA)
    {
    SLJIT_ASSERT(found == &backtrack->common.topbacktracks);
    set_jumps(backtrack->common.topbacktracks, LABEL());
    backtrack->common.topbacktracks = NULL;
    }
  }

common->leavelabel = save_leavelabel;
common->acceptlabel = save_acceptlabel;
common->leave = save_leave;
common->accept = save_accept;
return cc + 1 + LINK_SIZE;
}

static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table)
{
int condition = FALSE;
pcre_uchar *slotA = name_table;
pcre_uchar *slotB;
sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
sljit_w no_capture;
int i;

locals += refno & 0xff;
refno >>= 8;
no_capture = locals[1];

for (i = 0; i < name_count; i++)
  {
  if (GET2(slotA, 0) == refno) break;
  slotA += name_entry_size;
  }

if (i < name_count)
  {
  /* Found a name for the number - there can be only one; duplicate names
  for different numbers are allowed, but not vice versa. First scan down
  for duplicates. */

  slotB = slotA;
  while (slotB > name_table)
    {
    slotB -= name_entry_size;
    if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
      {
      condition = locals[GET2(slotB, 0) << 1] != no_capture;
      if (condition) break;
      }
    else break;
    }

  /* Scan up for duplicates */
  if (!condition)
    {
    slotB = slotA;
    for (i++; i < name_count; i++)
      {
      slotB += name_entry_size;
      if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
        {
        condition = locals[GET2(slotB, 0) << 1] != no_capture;
        if (condition) break;
        }
      else break;
      }
    }
  }
return condition;
}

static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table)
{
int condition = FALSE;
pcre_uchar *slotA = name_table;
pcre_uchar *slotB;
sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)];
int i;

for (i = 0; i < name_count; i++)
  {
  if (GET2(slotA, 0) == recno) break;
  slotA += name_entry_size;
  }

if (i < name_count)
  {
  /* Found a name for the number - there can be only one; duplicate
  names for different numbers are allowed, but not vice versa. First
  scan down for duplicates. */

  slotB = slotA;
  while (slotB > name_table)
    {
    slotB -= name_entry_size;
    if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
      {
      condition = GET2(slotB, 0) == group_num;
      if (condition) break;
      }
    else break;
    }

  /* Scan up for duplicates */
  if (!condition)
    {
    slotB = slotA;
    for (i++; i < name_count; i++)
      {
      slotB += name_entry_size;
      if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
        {
        condition = GET2(slotB, 0) == group_num;
        if (condition) break;
        }
      else break;
      }
    }
  }
return condition;
}

/*
  Handling bracketed expressions is probably the most complex part.

  Stack layout naming characters:
    S - Push the current STR_PTR
    0 - Push a 0 (NULL)
    A - Push the current STR_PTR. Needed for restoring the STR_PTR
        before the next alternative. Not pushed if there are no alternatives.
    M - Any values pushed by the current alternative. Can be empty, or anything.
    C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
    L - Push the previous local (pointed by localptr) to the stack
   () - opional values stored on the stack
  ()* - optonal, can be stored multiple times

  The following list shows the regular expression templates, their PCRE byte codes
  and stack layout supported by pcre-sljit.

  (?:)                     OP_BRA     | OP_KET                A M
  ()                       OP_CBRA    | OP_KET                C M
  (?:)+                    OP_BRA     | OP_KETRMAX        0   A M S   ( A M S )*
                           OP_SBRA    | OP_KETRMAX        0   L M S   ( L M S )*
  (?:)+?                   OP_BRA     | OP_KETRMIN        0   A M S   ( A M S )*
                           OP_SBRA    | OP_KETRMIN        0   L M S   ( L M S )*
  ()+                      OP_CBRA    | OP_KETRMAX        0   C M S   ( C M S )*
                           OP_SCBRA   | OP_KETRMAX        0   C M S   ( C M S )*
  ()+?                     OP_CBRA    | OP_KETRMIN        0   C M S   ( C M S )*
                           OP_SCBRA   | OP_KETRMIN        0   C M S   ( C M S )*
  (?:)?    OP_BRAZERO    | OP_BRA     | OP_KET            S ( A M 0 )
  (?:)??   OP_BRAMINZERO | OP_BRA     | OP_KET            S ( A M 0 )
  ()?      OP_BRAZERO    | OP_CBRA    | OP_KET            S ( C M 0 )
  ()??     OP_BRAMINZERO | OP_CBRA    | OP_KET            S ( C M 0 )
  (?:)*    OP_BRAZERO    | OP_BRA     | OP_KETRMAX      S 0 ( A M S )*
           OP_BRAZERO    | OP_SBRA    | OP_KETRMAX      S 0 ( L M S )*
  (?:)*?   OP_BRAMINZERO | OP_BRA     | OP_KETRMIN      S 0 ( A M S )*
           OP_BRAMINZERO | OP_SBRA    | OP_KETRMIN      S 0 ( L M S )*
  ()*      OP_BRAZERO    | OP_CBRA    | OP_KETRMAX      S 0 ( C M S )*
           OP_BRAZERO    | OP_SCBRA   | OP_KETRMAX      S 0 ( C M S )*
  ()*?     OP_BRAMINZERO | OP_CBRA    | OP_KETRMIN      S 0 ( C M S )*
           OP_BRAMINZERO | OP_SCBRA   | OP_KETRMIN      S 0 ( C M S )*


  Stack layout naming characters:
    A - Push the alternative index (starting from 0) on the stack.
        Not pushed if there is no alternatives.
    M - Any values pushed by the current alternative. Can be empty, or anything.

  The next list shows the possible content of a bracket:
  (|)     OP_*BRA    | OP_ALT ...         M A
  (?()|)  OP_*COND   | OP_ALT             M A
  (?>|)   OP_ONCE    | OP_ALT ...         [stack trace] M A
  (?>|)   OP_ONCE_NC | OP_ALT ...         [stack trace] M A
                                          Or nothing, if trace is unnecessary
*/

static pcre_uchar *compile_bracket_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
pcre_uchar opcode;
int localptr = 0;
int offset = 0;
int stacksize;
pcre_uchar *ccbegin;
pcre_uchar *trypath;
pcre_uchar bra = OP_BRA;
pcre_uchar ket;
assert_backtrack *assert;
BOOL has_alternatives;
struct sljit_jump *jump;
struct sljit_jump *skip;
struct sljit_label *rmaxlabel = NULL;
struct sljit_jump *braminzerojump = NULL;

PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);

if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
  {
  bra = *cc;
  cc++;
  opcode = *cc;
  }

opcode = *cc;
ccbegin = cc;
trypath = ccbegin + 1 + LINK_SIZE;

if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
  {
  /* Drop this bracket_backtrack. */
  parent->top = backtrack->prev;
  return bracketend(cc);
  }

ket = *(bracketend(cc) - 1 - LINK_SIZE);
SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
cc += GET(cc, 1);

has_alternatives = *cc == OP_ALT;
if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
  {
  has_alternatives = (*trypath == OP_RREF) ? FALSE : TRUE;
  if (*trypath == OP_NRREF)
    {
    stacksize = GET2(trypath, 1);
    if (common->currententry == NULL || stacksize == RREF_ANY)
      has_alternatives = FALSE;
    else if (common->currententry->start == 0)
      has_alternatives = stacksize != 0;
    else
      has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
    }
  }

if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
  opcode = OP_SCOND;
if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
  opcode = OP_ONCE;

if (opcode == OP_CBRA || opcode == OP_SCBRA)
  {
  /* Capturing brackets has a pre-allocated space. */
  offset = GET2(ccbegin, 1 + LINK_SIZE);
  localptr = OVECTOR_PRIV(offset);
  offset <<= 1;
  BACKTRACK_AS(bracket_backtrack)->localptr = localptr;
  trypath += IMM2_SIZE;
  }
else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
  {
  /* Other brackets simply allocate the next entry. */
  localptr = PRIV_DATA(ccbegin);
  SLJIT_ASSERT(localptr != 0);
  BACKTRACK_AS(bracket_backtrack)->localptr = localptr;
  if (opcode == OP_ONCE)
    BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE);
  }

/* Instructions before the first alternative. */
stacksize = 0;
if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
  stacksize++;
if (bra == OP_BRAZERO)
  stacksize++;

if (stacksize > 0)
  allocate_stack(common, stacksize);

stacksize = 0;
if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
  stacksize++;
  }

if (bra == OP_BRAZERO)
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);

if (bra == OP_BRAMINZERO)
  {
  /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  if (ket != OP_KETRMIN)
    {
    free_stack(common, 1);
    braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
    }
  else
    {
    if (opcode == OP_ONCE || opcode >= OP_SBRA)
      {
      jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
      /* Nothing stored during the first run. */
      skip = JUMP(SLJIT_JUMP);
      JUMPHERE(jump);
      /* Checking zero-length iteration. */
      if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
        {
        /* When we come from outside, localptr contains the previous STR_PTR. */
        braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        }
      else
        {
        /* Except when the whole stack frame must be saved. */
        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w));
        }
      JUMPHERE(skip);
      }
    else
      {
      jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
      JUMPHERE(jump);
      }
    }
  }

if (ket == OP_KETRMIN)
  BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL();

if (ket == OP_KETRMAX)
  {
  rmaxlabel = LABEL();
  if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
    BACKTRACK_AS(bracket_backtrack)->alttrypath = rmaxlabel;
  }

/* Handling capturing brackets and alternatives. */
if (opcode == OP_ONCE)
  {
  if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
    {
    /* Neither capturing brackets nor recursions are not found in the block. */
    if (ket == OP_KETRMIN)
      {
      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      allocate_stack(common, 2);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
      OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
      }
    else if (ket == OP_KETRMAX || has_alternatives)
      {
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
      allocate_stack(common, 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      }
    else
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
    }
  else
    {
    if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
      {
      allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2);
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
      init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE);
      }
    else
      {
      allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1);
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize));
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
      init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE);
      }
    }
  }
else if (opcode == OP_CBRA || opcode == OP_SCBRA)
  {
  /* Saving the previous values. */
  allocate_stack(common, 3);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
  }
else if (opcode == OP_SBRA || opcode == OP_SCOND)
  {
  /* Saving the previous value. */
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
  allocate_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
  }
else if (has_alternatives)
  {
  /* Pushing the starting string pointer. */
  allocate_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  }

/* Generating code for the first alternative. */
if (opcode == OP_COND || opcode == OP_SCOND)
  {
  if (*trypath == OP_CREF)
    {
    SLJIT_ASSERT(has_alternatives);
    add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),
      CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(trypath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
    trypath += 1 + IMM2_SIZE;
    }
  else if (*trypath == OP_NCREF)
    {
    SLJIT_ASSERT(has_alternatives);
    stacksize = GET2(trypath, 1);
    jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));

    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w)));
    GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0);
    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
    sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));
    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
    add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));

    JUMPHERE(jump);
    trypath += 1 + IMM2_SIZE;
    }
  else if (*trypath == OP_RREF || *trypath == OP_NRREF)
    {
    /* Never has other case. */
    BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;

    stacksize = GET2(trypath, 1);
    if (common->currententry == NULL)
      stacksize = 0;
    else if (stacksize == RREF_ANY)
      stacksize = 1;
    else if (common->currententry->start == 0)
      stacksize = stacksize == 0;
    else
      stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE);

    if (*trypath == OP_RREF || stacksize || common->currententry == NULL)
      {
      SLJIT_ASSERT(!has_alternatives);
      if (stacksize != 0)
        trypath += 1 + IMM2_SIZE;
      else
        {
        if (*cc == OP_ALT)
          {
          trypath = cc + 1 + LINK_SIZE;
          cc += GET(cc, 1);
          }
        else
          trypath = cc;
        }
      }
    else
      {
      SLJIT_ASSERT(has_alternatives);

      stacksize = GET2(trypath, 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE));
      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
      GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0);
      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
      sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups));
      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
      add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
      trypath += 1 + IMM2_SIZE;
      }
    }
  else
    {
    SLJIT_ASSERT(has_alternatives && *trypath >= OP_ASSERT && *trypath <= OP_ASSERTBACK_NOT);
    /* Similar code as PUSH_BACKTRACK macro. */
    assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));
    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
      return NULL;
    memset(assert, 0, sizeof(assert_backtrack));
    assert->common.cc = trypath;
    BACKTRACK_AS(bracket_backtrack)->u.assert = assert;
    trypath = compile_assert_trypath(common, trypath, assert, TRUE);
    }
  }

compile_trypath(common, trypath, cc, backtrack);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
  return NULL;

if (opcode == OP_ONCE)
  {
  if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
    {
    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
    /* TMP2 which is set here used by OP_KETRMAX below. */
    if (ket == OP_KETRMAX)
      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
    else if (ket == OP_KETRMIN)
      {
      /* Move the STR_PTR to the localptr. */
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
      }
    }
  else
    {
    stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1;
    OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize) * sizeof(sljit_w));
    if (ket == OP_KETRMAX)
      {
      /* TMP2 which is set here used by OP_KETRMAX below. */
      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
      }
    }
  }

stacksize = 0;
if (ket != OP_KET || bra != OP_BRA)
  stacksize++;
if (has_alternatives && opcode != OP_ONCE)
  stacksize++;

if (stacksize > 0)
  allocate_stack(common, stacksize);

stacksize = 0;
if (ket != OP_KET)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
  stacksize++;
  }
else if (bra != OP_BRA)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
  stacksize++;
  }

if (has_alternatives)
  {
  if (opcode != OP_ONCE)
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
  if (ket != OP_KETRMAX)
    BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL();
  }

/* Must be after the trypath label. */
if (offset != 0)
  {
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
  }

if (ket == OP_KETRMAX)
  {
  if (opcode == OP_ONCE || opcode >= OP_SBRA)
    {
    if (has_alternatives)
      BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL();
    /* Checking zero-length iteration. */
    if (opcode != OP_ONCE)
      {
      CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
      /* Drop STR_PTR for greedy plus quantifier. */
      if (bra != OP_BRAZERO)
        free_stack(common, 1);
      }
    else
      /* TMP2 must contain the starting STR_PTR. */
      CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
    }
  else
    JUMPTO(SLJIT_JUMP, rmaxlabel);
  BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL();
  }

if (bra == OP_BRAZERO)
  BACKTRACK_AS(bracket_backtrack)->zerotrypath = LABEL();

if (bra == OP_BRAMINZERO)
  {
  /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
  JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->trypath);
  if (braminzerojump != NULL)
    {
    JUMPHERE(braminzerojump);
    /* We need to release the end pointer to perform the
    backtrack for the zero-length iteration. When
    framesize is < 0, OP_ONCE will do the release itself. */
    if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)
      {
      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
      }
    else if (ket == OP_KETRMIN && opcode != OP_ONCE)
      free_stack(common, 1);
    }
  /* Continue to the normal backtrack. */
  }

if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
  decrease_call_count(common);

/* Skip the other alternatives. */
while (*cc == OP_ALT)
  cc += GET(cc, 1);
cc += 1 + LINK_SIZE;
return cc;
}

static pcre_uchar *compile_bracketpos_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
pcre_uchar opcode;
int localptr;
int cbraprivptr = 0;
int framesize;
int stacksize;
int offset = 0;
BOOL zero = FALSE;
pcre_uchar *ccbegin = NULL;
int stack;
struct sljit_label *loop = NULL;
struct jump_list *emptymatch = NULL;

PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);
if (*cc == OP_BRAPOSZERO)
  {
  zero = TRUE;
  cc++;
  }

opcode = *cc;
localptr = PRIV_DATA(cc);
SLJIT_ASSERT(localptr != 0);
BACKTRACK_AS(bracketpos_backtrack)->localptr = localptr;
switch(opcode)
  {
  case OP_BRAPOS:
  case OP_SBRAPOS:
  ccbegin = cc + 1 + LINK_SIZE;
  break;

  case OP_CBRAPOS:
  case OP_SCBRAPOS:
  offset = GET2(cc, 1 + LINK_SIZE);
  cbraprivptr = OVECTOR_PRIV(offset);
  offset <<= 1;
  ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
  break;

  default:
  SLJIT_ASSERT_STOP();
  break;
  }

framesize = get_framesize(common, cc, FALSE);
BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;
if (framesize < 0)
  {
  stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
  if (!zero)
    stacksize++;
  BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
  allocate_stack(common, stacksize);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);

  if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
    }
  else
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);

  if (!zero)
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1);
  }
else
  {
  stacksize = framesize + 1;
  if (!zero)
    stacksize++;
  if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
    stacksize++;
  BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
  allocate_stack(common, stacksize);

  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
  OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
  stack = 0;
  if (!zero)
    {
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
    stack++;
    }
  if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
    {
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
    stack++;
    }
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
  init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE);
  }

if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);

loop = LABEL();
while (*cc != OP_KETRPOS)
  {
  backtrack->top = NULL;
  backtrack->topbacktracks = NULL;
  cc += GET(cc, 1);

  compile_trypath(common, ccbegin, cc, backtrack);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    return NULL;

  if (framesize < 0)
    {
    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);

    if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
      }
    else
      {
      if (opcode == OP_SBRAPOS)
        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      }

    if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
      add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));

    if (!zero)
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
    }
  else
    {
    if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
      {
      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w));
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
      }
    else
      {
      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w));
      if (opcode == OP_SBRAPOS)
        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
      OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0);
      }

    if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
      add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));

    if (!zero)
      {
      if (framesize < 0)
        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
      else
        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      }
    }
  JUMPTO(SLJIT_JUMP, loop);
  flush_stubs(common);

  compile_backtrackpath(common, backtrack->top);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    return NULL;
  set_jumps(backtrack->topbacktracks, LABEL());

  if (framesize < 0)
    {
    if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
    else
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    }
  else
    {
    if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
      {
      /* Last alternative. */
      if (*cc == OP_KETRPOS)
        OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
      }
    else
      {
      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
      }
    }

  if (*cc == OP_KETRPOS)
    break;
  ccbegin = cc + 1 + LINK_SIZE;
  }

backtrack->topbacktracks = NULL;
if (!zero)
  {
  if (framesize < 0)
    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
  else /* TMP2 is set to [localptr] above. */
    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));
  }

/* None of them matched. */
set_jumps(emptymatch, LABEL());
decrease_call_count(common);
return cc + 1 + LINK_SIZE;
}

static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *arg1, int *arg2, pcre_uchar **end)
{
int class_len;

*opcode = *cc;
if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
  {
  cc++;
  *type = OP_CHAR;
  }
else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)
  {
  cc++;
  *type = OP_CHARI;
  *opcode -= OP_STARI - OP_STAR;
  }
else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)
  {
  cc++;
  *type = OP_NOT;
  *opcode -= OP_NOTSTAR - OP_STAR;
  }
else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)
  {
  cc++;
  *type = OP_NOTI;
  *opcode -= OP_NOTSTARI - OP_STAR;
  }
else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
  {
  cc++;
  *opcode -= OP_TYPESTAR - OP_STAR;
  *type = 0;
  }
else
  {
  SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS);
  *type = *opcode;
  cc++;
  class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
  *opcode = cc[class_len - 1];
  if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
    {
    *opcode -= OP_CRSTAR - OP_STAR;
    if (end != NULL)
      *end = cc + class_len;
    }
  else
    {
    SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE);
    *arg1 = GET2(cc, (class_len + IMM2_SIZE));
    *arg2 = GET2(cc, class_len);

    if (*arg2 == 0)
      {
      SLJIT_ASSERT(*arg1 != 0);
      *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO;
      }
    if (*arg1 == *arg2)
      *opcode = OP_EXACT;

    if (end != NULL)
      *end = cc + class_len + 2 * IMM2_SIZE;
    }
  return cc;
  }

if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO)
  {
  *arg1 = GET2(cc, 0);
  cc += IMM2_SIZE;
  }

if (*type == 0)
  {
  *type = *cc;
  if (end != NULL)
    *end = next_opcode(common, cc);
  cc++;
  return cc;
  }

if (end != NULL)
  {
  *end = cc + 1;
#ifdef SUPPORT_UTF
  if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
#endif
  }
return cc;
}

static pcre_uchar *compile_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
pcre_uchar opcode;
pcre_uchar type;
int arg1 = -1, arg2 = -1;
pcre_uchar* end;
jump_list *nomatch = NULL;
struct sljit_jump *jump = NULL;
struct sljit_label *label;

PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);

cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);

switch(opcode)
  {
  case OP_STAR:
  case OP_PLUS:
  case OP_UPTO:
  case OP_CRRANGE:
  if (type == OP_ANYNL || type == OP_EXTUNI)
    {
    if (opcode == OP_STAR || opcode == OP_UPTO)
      {
      allocate_stack(common, 2);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
      }
    else
      {
      allocate_stack(common, 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      }
    if (opcode == OP_UPTO || opcode == OP_CRRANGE)
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);

    label = LABEL();
    compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
    if (opcode == OP_UPTO || opcode == OP_CRRANGE)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
      if (opcode == OP_CRRANGE && arg2 > 0)
        CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label);
      if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0))
        jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
      }

    allocate_stack(common, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    JUMPTO(SLJIT_JUMP, label);
    if (jump != NULL)
      JUMPHERE(jump);
    }
  else
    {
    if (opcode == OP_PLUS)
      compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
    allocate_stack(common, 2);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
    label = LABEL();
    compile_char1_trypath(common, type, cc, &nomatch);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))
      {
      OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
      JUMPTO(SLJIT_JUMP, label);
      }
    else
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
      CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
      }
    set_jumps(nomatch, LABEL());
    if (opcode == OP_CRRANGE)
      add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1));
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    }
  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
  break;

  case OP_MINSTAR:
  case OP_MINPLUS:
  if (opcode == OP_MINPLUS)
    compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
  allocate_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
  break;

  case OP_MINUPTO:
  case OP_CRMINRANGE:
  allocate_stack(common, 2);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
  if (opcode == OP_CRMINRANGE)
    add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
  break;

  case OP_QUERY:
  case OP_MINQUERY:
  allocate_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  if (opcode == OP_QUERY)
    compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
  BACKTRACK_AS(iterator_backtrack)->trypath = LABEL();
  break;

  case OP_EXACT:
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
  label = LABEL();
  compile_char1_trypath(common, type, cc, &backtrack->topbacktracks);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
  break;

  case OP_POSSTAR:
  case OP_POSPLUS:
  case OP_POSUPTO:
  if (opcode != OP_POSSTAR)
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
  label = LABEL();
  compile_char1_trypath(common, type, cc, &nomatch);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
  if (opcode != OP_POSUPTO)
    {
    if (opcode == OP_POSPLUS)
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2);
    JUMPTO(SLJIT_JUMP, label);
    }
  else
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
    OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
    }
  set_jumps(nomatch, LABEL());
  if (opcode == OP_POSPLUS)
    add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
  break;

  case OP_POSQUERY:
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
  compile_char1_trypath(common, type, cc, &nomatch);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
  set_jumps(nomatch, LABEL());
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
  break;

  default:
  SLJIT_ASSERT_STOP();
  break;
  }

decrease_call_count(common);
return end;
}

static SLJIT_INLINE pcre_uchar *compile_fail_accept_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;

PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);

if (*cc == OP_FAIL)
  {
  add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
  return cc + 1;
  }

if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL)
  {
  /* No need to check notempty conditions. */
  if (common->acceptlabel == NULL)
    add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
  else
    JUMPTO(SLJIT_JUMP, common->acceptlabel);
  return cc + 1;
  }

if (common->acceptlabel == NULL)
  add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)));
else
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
if (common->acceptlabel == NULL)
  add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));
else
  CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
if (common->acceptlabel == NULL)
  add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
else
  CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
return cc + 1;
}

static SLJIT_INLINE pcre_uchar *compile_close_trypath(compiler_common *common, pcre_uchar *cc)
{
DEFINE_COMPILER;
int offset = GET2(cc, 1);

/* Data will be discarded anyway... */
if (common->currententry != NULL)
  return cc + 1 + IMM2_SIZE;

OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));
offset <<= 1;
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
return cc + 1 + IMM2_SIZE;
}

static void compile_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;

while (cc < ccend)
  {
  switch(*cc)
    {
    case OP_SOD:
    case OP_SOM:
    case OP_NOT_WORD_BOUNDARY:
    case OP_WORD_BOUNDARY:
    case OP_NOT_DIGIT:
    case OP_DIGIT:
    case OP_NOT_WHITESPACE:
    case OP_WHITESPACE:
    case OP_NOT_WORDCHAR:
    case OP_WORDCHAR:
    case OP_ANY:
    case OP_ALLANY:
    case OP_ANYBYTE:
    case OP_NOTPROP:
    case OP_PROP:
    case OP_ANYNL:
    case OP_NOT_HSPACE:
    case OP_HSPACE:
    case OP_NOT_VSPACE:
    case OP_VSPACE:
    case OP_EXTUNI:
    case OP_EODN:
    case OP_EOD:
    case OP_CIRC:
    case OP_CIRCM:
    case OP_DOLL:
    case OP_DOLLM:
    case OP_NOT:
    case OP_NOTI:
    case OP_REVERSE:
    cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
    break;

    case OP_SET_SOM:
    PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
    allocate_stack(common, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
    cc++;
    break;

    case OP_CHAR:
    case OP_CHARI:
    if (common->mode == JIT_COMPILE)
      cc = compile_charn_trypath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
    else
      cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
    break;

    case OP_STAR:
    case OP_MINSTAR:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_QUERY:
    case OP_MINQUERY:
    case OP_UPTO:
    case OP_MINUPTO:
    case OP_EXACT:
    case OP_POSSTAR:
    case OP_POSPLUS:
    case OP_POSQUERY:
    case OP_POSUPTO:
    case OP_STARI:
    case OP_MINSTARI:
    case OP_PLUSI:
    case OP_MINPLUSI:
    case OP_QUERYI:
    case OP_MINQUERYI:
    case OP_UPTOI:
    case OP_MINUPTOI:
    case OP_EXACTI:
    case OP_POSSTARI:
    case OP_POSPLUSI:
    case OP_POSQUERYI:
    case OP_POSUPTOI:
    case OP_NOTSTAR:
    case OP_NOTMINSTAR:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTQUERY:
    case OP_NOTMINQUERY:
    case OP_NOTUPTO:
    case OP_NOTMINUPTO:
    case OP_NOTEXACT:
    case OP_NOTPOSSTAR:
    case OP_NOTPOSPLUS:
    case OP_NOTPOSQUERY:
    case OP_NOTPOSUPTO:
    case OP_NOTSTARI:
    case OP_NOTMINSTARI:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUSI:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERYI:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTOI:
    case OP_NOTEXACTI:
    case OP_NOTPOSSTARI:
    case OP_NOTPOSPLUSI:
    case OP_NOTPOSQUERYI:
    case OP_NOTPOSUPTOI:
    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    case OP_TYPEEXACT:
    case OP_TYPEPOSSTAR:
    case OP_TYPEPOSPLUS:
    case OP_TYPEPOSQUERY:
    case OP_TYPEPOSUPTO:
    cc = compile_iterator_trypath(common, cc, parent);
    break;

    case OP_CLASS:
    case OP_NCLASS:
    if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE)
      cc = compile_iterator_trypath(common, cc, parent);
    else
      cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
    break;

#if defined SUPPORT_UTF || defined COMPILE_PCRE16
    case OP_XCLASS:
    if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)
      cc = compile_iterator_trypath(common, cc, parent);
    else
      cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
    break;
#endif

    case OP_REF:
    case OP_REFI:
    if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE)
      cc = compile_ref_iterator_trypath(common, cc, parent);
    else
      cc = compile_ref_trypath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
    break;

    case OP_RECURSE:
    cc = compile_recurse_trypath(common, cc, parent);
    break;

    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
    cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
    break;

    case OP_BRAMINZERO:
    PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);
    cc = bracketend(cc + 1);
    if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
      {
      allocate_stack(common, 1);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
      }
    else
      {
      allocate_stack(common, 2);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
      }
    BACKTRACK_AS(braminzero_backtrack)->trypath = LABEL();
    if (cc[1] > OP_ASSERTBACK_NOT)
      decrease_call_count(common);
    break;

    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_BRA:
    case OP_CBRA:
    case OP_COND:
    case OP_SBRA:
    case OP_SCBRA:
    case OP_SCOND:
    cc = compile_bracket_trypath(common, cc, parent);
    break;

    case OP_BRAZERO:
    if (cc[1] > OP_ASSERTBACK_NOT)
      cc = compile_bracket_trypath(common, cc, parent);
    else
      {
      PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
      cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
      }
    break;

    case OP_BRAPOS:
    case OP_CBRAPOS:
    case OP_SBRAPOS:
    case OP_SCBRAPOS:
    case OP_BRAPOSZERO:
    cc = compile_bracketpos_trypath(common, cc, parent);
    break;

    case OP_MARK:
    PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
    SLJIT_ASSERT(common->mark_ptr != 0);
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
    allocate_stack(common, 1);
    OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)(cc + 2));
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
    cc += 1 + 2 + cc[1];
    break;

    case OP_COMMIT:
    PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
    cc += 1;
    break;

    case OP_FAIL:
    case OP_ACCEPT:
    case OP_ASSERT_ACCEPT:
    cc = compile_fail_accept_trypath(common, cc, parent);
    break;

    case OP_CLOSE:
    cc = compile_close_trypath(common, cc);
    break;

    case OP_SKIPZERO:
    cc = bracketend(cc + 1);
    break;

    default:
    SLJIT_ASSERT_STOP();
    return;
    }
  if (cc == NULL)
    return;
  }
SLJIT_ASSERT(cc == ccend);
}

#undef PUSH_BACKTRACK
#undef PUSH_BACKTRACK_NOVALUE
#undef BACKTRACK_AS

#define COMPILE_BACKTRACKPATH(current) \
  do \
    { \
    compile_backtrackpath(common, (current)); \
    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
      return; \
    } \
  while (0)

#define CURRENT_AS(type) ((type *)current)

static void compile_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
pcre_uchar *cc = current->cc;
pcre_uchar opcode;
pcre_uchar type;
int arg1 = -1, arg2 = -1;
struct sljit_label *label = NULL;
struct sljit_jump *jump = NULL;
jump_list *jumplist = NULL;

cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);

switch(opcode)
  {
  case OP_STAR:
  case OP_PLUS:
  case OP_UPTO:
  case OP_CRRANGE:
  if (type == OP_ANYNL || type == OP_EXTUNI)
    {
    set_jumps(current->topbacktracks, LABEL());
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    free_stack(common, 1);
    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
    }
  else
    {
    if (opcode <= OP_PLUS || opcode == OP_UPTO)
      arg2 = 0;
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, arg2 + 1);
    OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, SLJIT_IMM, 1);
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    skip_char_back(common);
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
    if (opcode == OP_CRRANGE)
      set_jumps(current->topbacktracks, LABEL());
    JUMPHERE(jump);
    free_stack(common, 2);
    if (opcode == OP_PLUS)
      set_jumps(current->topbacktracks, LABEL());
    }
  break;

  case OP_MINSTAR:
  case OP_MINPLUS:
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  compile_char1_trypath(common, type, cc, &jumplist);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
  set_jumps(jumplist, LABEL());
  free_stack(common, 1);
  if (opcode == OP_MINPLUS)
    set_jumps(current->topbacktracks, LABEL());
  break;

  case OP_MINUPTO:
  case OP_CRMINRANGE:
  if (opcode == OP_CRMINRANGE)
    {
    label = LABEL();
    set_jumps(current->topbacktracks, label);
    }
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  compile_char1_trypath(common, type, cc, &jumplist);

  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);

  if (opcode == OP_CRMINRANGE)
    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);

  if (opcode == OP_CRMINRANGE && arg1 == 0)
    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
  else
    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_backtrack)->trypath);

  set_jumps(jumplist, LABEL());
  free_stack(common, 2);
  break;

  case OP_QUERY:
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
  jump = JUMP(SLJIT_JUMP);
  set_jumps(current->topbacktracks, LABEL());
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
  JUMPHERE(jump);
  free_stack(common, 1);
  break;

  case OP_MINQUERY:
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
  compile_char1_trypath(common, type, cc, &jumplist);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath);
  set_jumps(jumplist, LABEL());
  JUMPHERE(jump);
  free_stack(common, 1);
  break;

  case OP_EXACT:
  case OP_POSPLUS:
  set_jumps(current->topbacktracks, LABEL());
  break;

  case OP_POSSTAR:
  case OP_POSQUERY:
  case OP_POSUPTO:
  break;

  default:
  SLJIT_ASSERT_STOP();
  break;
  }
}

static void compile_ref_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
pcre_uchar *cc = current->cc;
pcre_uchar type;

type = cc[1 + IMM2_SIZE];
if ((type & 0x1) == 0)
  {
  set_jumps(current->topbacktracks, LABEL());
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  free_stack(common, 1);
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
  return;
  }

OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath);
set_jumps(current->topbacktracks, LABEL());
free_stack(common, 2);
}

static void compile_recurse_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;

set_jumps(current->topbacktracks, LABEL());

if (common->has_set_som && common->mark_ptr != 0)
  {
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
  free_stack(common, 2);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
  }
else if (common->has_set_som || common->mark_ptr != 0)
  {
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  free_stack(common, 1);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0);
  }
}

static void compile_assert_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
pcre_uchar *cc = current->cc;
pcre_uchar bra = OP_BRA;
struct sljit_jump *brajump = NULL;

SLJIT_ASSERT(*cc != OP_BRAMINZERO);
if (*cc == OP_BRAZERO)
  {
  bra = *cc;
  cc++;
  }

if (bra == OP_BRAZERO)
  {
  SLJIT_ASSERT(current->topbacktracks == NULL);
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  }

if (CURRENT_AS(assert_backtrack)->framesize < 0)
  {
  set_jumps(current->topbacktracks, LABEL());

  if (bra == OP_BRAZERO)
    {
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath);
    free_stack(common, 1);
    }
  return;
  }

if (bra == OP_BRAZERO)
  {
  if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
    {
    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath);
    free_stack(common, 1);
    return;
    }
  free_stack(common, 1);
  brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
  }

if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
  {
  OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr);
  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_w));

  set_jumps(current->topbacktracks, LABEL());
  }
else
  set_jumps(current->topbacktracks, LABEL());

if (bra == OP_BRAZERO)
  {
  /* We know there is enough place on the stack. */
  OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
  JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->trypath);
  JUMPHERE(brajump);
  }
}

static void compile_bracket_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
int opcode;
int offset = 0;
int localptr = CURRENT_AS(bracket_backtrack)->localptr;
int stacksize;
int count;
pcre_uchar *cc = current->cc;
pcre_uchar *ccbegin;
pcre_uchar *ccprev;
jump_list *jumplist = NULL;
jump_list *jumplistitem = NULL;
pcre_uchar bra = OP_BRA;
pcre_uchar ket;
assert_backtrack *assert;
BOOL has_alternatives;
struct sljit_jump *brazero = NULL;
struct sljit_jump *once = NULL;
struct sljit_jump *cond = NULL;
struct sljit_label *rminlabel = NULL;

if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
  {
  bra = *cc;
  cc++;
  }

opcode = *cc;
ccbegin = cc;
ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);
cc += GET(cc, 1);
has_alternatives = *cc == OP_ALT;
if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
  has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;
if (opcode == OP_CBRA || opcode == OP_SCBRA)
  offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
  opcode = OP_SCOND;
if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
  opcode = OP_ONCE;

if (ket == OP_KETRMAX)
  {
  if (bra == OP_BRAZERO)
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    free_stack(common, 1);
    brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0);
    }
  }
else if (ket == OP_KETRMIN)
  {
  if (bra != OP_BRAMINZERO)
    {
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    if (opcode >= OP_SBRA || opcode == OP_ONCE)
      {
      /* Checking zero-length iteration. */
      if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_backtrack)->recursivetrypath);
      else
        {
        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_backtrack)->recursivetrypath);
        }
      if (opcode != OP_ONCE)
        free_stack(common, 1);
      }
    else
      JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursivetrypath);
    }
  rminlabel = LABEL();
  }
else if (bra == OP_BRAZERO)
  {
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  free_stack(common, 1);
  brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
  }

if (SLJIT_UNLIKELY(opcode == OP_ONCE))
  {
  if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
    {
    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
    add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
    }
  once = JUMP(SLJIT_JUMP);
  }
else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
  {
  if (has_alternatives)
    {
    /* Always exactly one alternative. */
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    free_stack(common, 1);

    jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
    if (SLJIT_UNLIKELY(!jumplistitem))
      return;
    jumplist = jumplistitem;
    jumplistitem->next = NULL;
    jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1);
    }
  }
else if (*cc == OP_ALT)
  {
  /* Build a jump list. Get the last successfully matched branch index. */
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  free_stack(common, 1);
  count = 1;
  do
    {
    /* Append as the last item. */
    if (jumplist != NULL)
      {
      jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list));
      jumplistitem = jumplistitem->next;
      }
    else
      {
      jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
      jumplist = jumplistitem;
      }

    if (SLJIT_UNLIKELY(!jumplistitem))
      return;

    jumplistitem->next = NULL;
    jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++);
    cc += GET(cc, 1);
    }
  while (*cc == OP_ALT);

  cc = ccbegin + GET(ccbegin, 1);
  }

COMPILE_BACKTRACKPATH(current->top);
if (current->topbacktracks)
  set_jumps(current->topbacktracks, LABEL());

if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
  {
  /* Conditional block always has at most one alternative. */
  if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
    {
    SLJIT_ASSERT(has_alternatives);
    assert = CURRENT_AS(bracket_backtrack)->u.assert;
    if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
      {
      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
      }
    cond = JUMP(SLJIT_JUMP);
    set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
    }
  else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)
    {
    SLJIT_ASSERT(has_alternatives);
    cond = JUMP(SLJIT_JUMP);
    set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());
    }
  else
    SLJIT_ASSERT(!has_alternatives);
  }

if (has_alternatives)
  {
  count = 1;
  do
    {
    current->top = NULL;
    current->topbacktracks = NULL;
    current->nextbacktracks = NULL;
    if (*cc == OP_ALT)
      {
      ccprev = cc + 1 + LINK_SIZE;
      cc += GET(cc, 1);
      if (opcode != OP_COND && opcode != OP_SCOND)
        {
        if (localptr != 0 && opcode != OP_ONCE)
          OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        else
          OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
        }
      compile_trypath(common, ccprev, cc, current);
      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
        return;
      }

    /* Instructions after the current alternative is succesfully matched. */
    /* There is a similar code in compile_bracket_trypath. */
    if (opcode == OP_ONCE)
      {
      if (CURRENT_AS(bracket_backtrack)->u.framesize < 0)
        {
        OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
        /* TMP2 which is set here used by OP_KETRMAX below. */
        if (ket == OP_KETRMAX)
          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
        else if (ket == OP_KETRMIN)
          {
          /* Move the STR_PTR to the localptr. */
          OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
          }
        }
      else
        {
        OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize + 2) * sizeof(sljit_w));
        if (ket == OP_KETRMAX)
          {
          /* TMP2 which is set here used by OP_KETRMAX below. */
          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
          }
        }
      }

    stacksize = 0;
    if (opcode != OP_ONCE)
      stacksize++;
    if (ket != OP_KET || bra != OP_BRA)
      stacksize++;

    if (stacksize > 0) {
      if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
        allocate_stack(common, stacksize);
      else
        {
        /* We know we have place at least for one item on the top of the stack. */
        SLJIT_ASSERT(stacksize == 1);
        OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
        }
    }

    stacksize = 0;
    if (ket != OP_KET || bra != OP_BRA)
      {
      if (ket != OP_KET)
        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
      else
        OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
      stacksize++;
      }

    if (opcode != OP_ONCE)
      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++);

    if (offset != 0)
      {
      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
      }

    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alttrypath);

    if (opcode != OP_ONCE)
      {
      SLJIT_ASSERT(jumplist);
      JUMPHERE(jumplist->jump);
      jumplist = jumplist->next;
      }

    COMPILE_BACKTRACKPATH(current->top);
    if (current->topbacktracks)
      set_jumps(current->topbacktracks, LABEL());
    SLJIT_ASSERT(!current->nextbacktracks);
    }
  while (*cc == OP_ALT);
  SLJIT_ASSERT(!jumplist);

  if (cond != NULL)
    {
    SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
    assert = CURRENT_AS(bracket_backtrack)->u.assert;
    if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)

      {
      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
      }
    JUMPHERE(cond);
    }

  /* Free the STR_PTR. */
  if (localptr == 0)
    free_stack(common, 1);
  }

if (offset != 0)
  {
  /* Using both tmp register is better for instruction scheduling. */
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2));
  free_stack(common, 3);
  }
else if (opcode == OP_SBRA || opcode == OP_SCOND)
  {
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0));
  free_stack(common, 1);
  }
else if (opcode == OP_ONCE)
  {
  cc = ccbegin + GET(ccbegin, 1);
  if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
    {
    /* Reset head and drop saved frame. */
    stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;
    free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize);
    }
  else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
    {
    /* The STR_PTR must be released. */
    free_stack(common, 1);
    }

  JUMPHERE(once);
  /* Restore previous localptr */
  if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_w));
  else if (ket == OP_KETRMIN)
    {
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    /* See the comment below. */
    free_stack(common, 2);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
    }
  }

if (ket == OP_KETRMAX)
  {
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  if (bra != OP_BRAZERO)
    free_stack(common, 1);
  CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursivetrypath);
  if (bra == OP_BRAZERO)
    {
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath);
    JUMPHERE(brazero);
    free_stack(common, 1);
    }
  }
else if (ket == OP_KETRMIN)
  {
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));

  /* OP_ONCE removes everything in case of a backtrack, so we don't
  need to explicitly release the STR_PTR. The extra release would
  affect badly the free_stack(2) above. */
  if (opcode != OP_ONCE)
    free_stack(common, 1);
  CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel);
  if (opcode == OP_ONCE)
    free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
  else if (bra == OP_BRAMINZERO)
    free_stack(common, 1);
  }
else if (bra == OP_BRAZERO)
  {
  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
  JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath);
  JUMPHERE(brazero);
  }
}

static void compile_bracketpos_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
int offset;
struct sljit_jump *jump;

if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)
  {
  if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
    {
    offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
    }
  set_jumps(current->topbacktracks, LABEL());
  free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
  return;
  }

OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr);
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));

if (current->topbacktracks)
  {
  jump = JUMP(SLJIT_JUMP);
  set_jumps(current->topbacktracks, LABEL());
  /* Drop the stack frame. */
  free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
  JUMPHERE(jump);
  }
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_w));
}

static void compile_braminzero_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
assert_backtrack backtrack;

current->top = NULL;
current->topbacktracks = NULL;
current->nextbacktracks = NULL;
if (current->cc[1] > OP_ASSERTBACK_NOT)
  {
  /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */
  compile_bracket_trypath(common, current->cc, current);
  compile_bracket_backtrackpath(common, current->top);
  }
else
  {
  memset(&backtrack, 0, sizeof(backtrack));
  backtrack.common.cc = current->cc;
  backtrack.trypath = CURRENT_AS(braminzero_backtrack)->trypath;
  /* Manual call of compile_assert_trypath. */
  compile_assert_trypath(common, current->cc, &backtrack, FALSE);
  }
SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);
}

static void compile_backtrackpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;

while (current)
  {
  if (current->nextbacktracks != NULL)
    set_jumps(current->nextbacktracks, LABEL());
  switch(*current->cc)
    {
    case OP_SET_SOM:
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    free_stack(common, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0);
    break;

    case OP_STAR:
    case OP_MINSTAR:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_QUERY:
    case OP_MINQUERY:
    case OP_UPTO:
    case OP_MINUPTO:
    case OP_EXACT:
    case OP_POSSTAR:
    case OP_POSPLUS:
    case OP_POSQUERY:
    case OP_POSUPTO:
    case OP_STARI:
    case OP_MINSTARI:
    case OP_PLUSI:
    case OP_MINPLUSI:
    case OP_QUERYI:
    case OP_MINQUERYI:
    case OP_UPTOI:
    case OP_MINUPTOI:
    case OP_EXACTI:
    case OP_POSSTARI:
    case OP_POSPLUSI:
    case OP_POSQUERYI:
    case OP_POSUPTOI:
    case OP_NOTSTAR:
    case OP_NOTMINSTAR:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTQUERY:
    case OP_NOTMINQUERY:
    case OP_NOTUPTO:
    case OP_NOTMINUPTO:
    case OP_NOTEXACT:
    case OP_NOTPOSSTAR:
    case OP_NOTPOSPLUS:
    case OP_NOTPOSQUERY:
    case OP_NOTPOSUPTO:
    case OP_NOTSTARI:
    case OP_NOTMINSTARI:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUSI:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERYI:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTOI:
    case OP_NOTEXACTI:
    case OP_NOTPOSSTARI:
    case OP_NOTPOSPLUSI:
    case OP_NOTPOSQUERYI:
    case OP_NOTPOSUPTOI:
    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    case OP_TYPEEXACT:
    case OP_TYPEPOSSTAR:
    case OP_TYPEPOSPLUS:
    case OP_TYPEPOSQUERY:
    case OP_TYPEPOSUPTO:
    case OP_CLASS:
    case OP_NCLASS:
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
    case OP_XCLASS:
#endif
    compile_iterator_backtrackpath(common, current);
    break;

    case OP_REF:
    case OP_REFI:
    compile_ref_iterator_backtrackpath(common, current);
    break;

    case OP_RECURSE:
    compile_recurse_backtrackpath(common, current);
    break;

    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    compile_assert_backtrackpath(common, current);
    break;

    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_BRA:
    case OP_CBRA:
    case OP_COND:
    case OP_SBRA:
    case OP_SCBRA:
    case OP_SCOND:
    compile_bracket_backtrackpath(common, current);
    break;

    case OP_BRAZERO:
    if (current->cc[1] > OP_ASSERTBACK_NOT)
      compile_bracket_backtrackpath(common, current);
    else
      compile_assert_backtrackpath(common, current);
    break;

    case OP_BRAPOS:
    case OP_CBRAPOS:
    case OP_SBRAPOS:
    case OP_SCBRAPOS:
    case OP_BRAPOSZERO:
    compile_bracketpos_backtrackpath(common, current);
    break;

    case OP_BRAMINZERO:
    compile_braminzero_backtrackpath(common, current);
    break;

    case OP_MARK:
    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
    free_stack(common, 1);
    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
    break;

    case OP_COMMIT:
    OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
    if (common->leavelabel == NULL)
      add_jump(compiler, &common->leave, JUMP(SLJIT_JUMP));
    else
      JUMPTO(SLJIT_JUMP, common->leavelabel);
    break;

    case OP_FAIL:
    case OP_ACCEPT:
    case OP_ASSERT_ACCEPT:
    set_jumps(current->topbacktracks, LABEL());
    break;

    default:
    SLJIT_ASSERT_STOP();
    break;
    }
  current = current->prev;
  }
}

static SLJIT_INLINE void compile_recurse(compiler_common *common)
{
DEFINE_COMPILER;
pcre_uchar *cc = common->start + common->currententry->start;
pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
pcre_uchar *ccend = bracketend(cc);
int localsize = get_localsize(common, ccbegin, ccend);
int framesize = get_framesize(common, cc, TRUE);
int alternativesize;
BOOL needsframe;
backtrack_common altbacktrack;
struct sljit_label *save_leavelabel = common->leavelabel;
jump_list *save_leave = common->leave;
struct sljit_jump *jump;

SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
needsframe = framesize >= 0;
if (!needsframe)
  framesize = 0;
alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;

SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head != 0);
common->currententry->entry = LABEL();
set_jumps(common->currententry->calls, common->currententry->entry);

sljit_emit_fast_enter(compiler, TMP2, 0);
allocate_stack(common, localsize + framesize + alternativesize);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);
copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, STACK_TOP, 0);
if (needsframe)
  init_frame(common, cc, framesize + alternativesize - 1, alternativesize, TRUE);

if (alternativesize > 0)
  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);

memset(&altbacktrack, 0, sizeof(backtrack_common));
common->leavelabel = NULL;
common->acceptlabel = NULL;
common->leave = NULL;
common->accept = NULL;
altbacktrack.cc = ccbegin;
cc += GET(cc, 1);
while (1)
  {
  altbacktrack.top = NULL;
  altbacktrack.topbacktracks = NULL;

  if (altbacktrack.cc != ccbegin)
    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));

  compile_trypath(common, altbacktrack.cc, cc, &altbacktrack);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    {
    common->leavelabel = save_leavelabel;
    common->leave = save_leave;
    return;
    }

  add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));

  compile_backtrackpath(common, altbacktrack.top);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    {
    common->leavelabel = save_leavelabel;
    common->leave = save_leave;
    return;
    }
  set_jumps(altbacktrack.topbacktracks, LABEL());

  if (*cc != OP_ALT)
    break;

  altbacktrack.cc = cc + 1 + LINK_SIZE;
  cc += GET(cc, 1);
  }
/* None of them matched. */
if (common->leave != NULL)
  set_jumps(common->leave, LABEL());

OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
jump = JUMP(SLJIT_JUMP);

set_jumps(common->accept, LABEL());
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head);
if (needsframe)
  {
  OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
  OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
  }
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);

JUMPHERE(jump);
copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize);
free_stack(common, localsize + framesize + alternativesize);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));
OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, TMP2, 0);
sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);

common->leavelabel = save_leavelabel;
common->leave = save_leave;
}

#undef COMPILE_BACKTRACKPATH
#undef CURRENT_AS

void
PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode)
{
struct sljit_compiler *compiler;
backtrack_common rootbacktrack;
compiler_common common_data;
compiler_common *common = &common_data;
const pcre_uint8 *tables = re->tables;
pcre_study_data *study;
int localsize;
pcre_uchar *ccend;
executable_functions *functions;
void *executable_func;
sljit_uw executable_size;
struct sljit_label *mainloop = NULL;
struct sljit_label *empty_match_found;
struct sljit_label *empty_match_backtrack;
struct sljit_jump *jump;
struct sljit_jump *reqbyte_notfound = NULL;
struct sljit_jump *empty_match;

SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
study = extra->study_data;

if (!tables)
  tables = PRIV(default_tables);

memset(&rootbacktrack, 0, sizeof(backtrack_common));
memset(common, 0, sizeof(compiler_common));
rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;

common->start = rootbacktrack.cc;
common->fcc = tables + fcc_offset;
common->lcc = (sljit_w)(tables + lcc_offset);
common->mode = mode;
common->nltype = NLTYPE_FIXED;
switch(re->options & PCRE_NEWLINE_BITS)
  {
  case 0:
  /* Compile-time default */
  switch (NEWLINE)
    {
    case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
    case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
    default: common->newline = NEWLINE; break;
    }
  break;
  case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
  case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
  case PCRE_NEWLINE_CR+
       PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
  case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
  case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
  default: return;
  }
if ((re->options & PCRE_BSR_ANYCRLF) != 0)
  common->bsr_nltype = NLTYPE_ANYCRLF;
else if ((re->options & PCRE_BSR_UNICODE) != 0)
  common->bsr_nltype = NLTYPE_ANY;
else
  {
#ifdef BSR_ANYCRLF
  common->bsr_nltype = NLTYPE_ANYCRLF;
#else
  common->bsr_nltype = NLTYPE_ANY;
#endif
  }
common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
common->ctypes = (sljit_w)(tables + ctypes_offset);
common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset);
common->name_count = re->name_count;
common->name_entry_size = re->name_entry_size;
common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
#ifdef SUPPORT_UTF
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
common->utf = (re->options & PCRE_UTF8) != 0;
#ifdef SUPPORT_UCP
common->use_ucp = (re->options & PCRE_UCP) != 0;
#endif
#endif /* SUPPORT_UTF */
ccend = bracketend(rootbacktrack.cc);

/* Calculate the local space size on the stack. */
common->ovector_start = CALL_LIMIT + sizeof(sljit_w);

SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
localsize = get_localspace(common, rootbacktrack.cc, ccend);
if (localsize < 0)
  return;

/* Checking flags and updating ovector_start. */
if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
  {
  common->req_char_ptr = common->ovector_start;
  common->ovector_start += sizeof(sljit_w);
  }
if (mode != JIT_COMPILE)
  {
  common->start_used_ptr = common->ovector_start;
  common->ovector_start += sizeof(sljit_w);
  if (mode == JIT_PARTIAL_SOFT_COMPILE)
    {
    common->hit_start = common->ovector_start;
    common->ovector_start += sizeof(sljit_w);
    }
  }
if ((re->options & PCRE_FIRSTLINE) != 0)
  {
  common->first_line_end = common->ovector_start;
  common->ovector_start += sizeof(sljit_w);
  }

/* Aligning ovector to even number of sljit words. */
if ((common->ovector_start & sizeof(sljit_w)) != 0)
  common->ovector_start += sizeof(sljit_w);

SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w);
localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
if (localsize > SLJIT_MAX_LOCAL_SIZE)
  return;
common->localptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int));
if (!common->localptrs)
  return;
memset(common->localptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);

compiler = sljit_create_compiler();
if (!compiler)
  {
  SLJIT_FREE(common->localptrs);
  return;
  }
common->compiler = compiler;

/* Main pcre_jit_exec entry. */
sljit_emit_enter(compiler, 1, 5, 5, localsize);

/* Register init. */
reset_ovector(common, (re->top_bracket + 1) * 2);
if (common->req_char_ptr != 0)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, SLJIT_TEMPORARY_REG1, 0);

OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0);
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);

if (mode == JIT_PARTIAL_SOFT_COMPILE)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);

/* Main part of the matching */
if ((re->options & PCRE_ANCHORED) == 0)
  {
  mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
  /* Forward search if possible. */
  if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
    {
    if ((re->flags & PCRE_FIRSTSET) != 0)
      fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
    else if ((re->flags & PCRE_STARTLINE) != 0)
      fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
    else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
      fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
    }
  }
if (common->req_char_ptr != 0)
  reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);

/* Store the current STR_PTR in OVECTOR(0). */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
/* Copy the limit of allowed recursions. */
OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
if (common->mark_ptr != 0)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);
/* Copy the beginning of the string. */
if (mode == JIT_PARTIAL_SOFT_COMPILE)
  {
  jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
  JUMPHERE(jump);
  }
else if (mode == JIT_PARTIAL_HARD_COMPILE)
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);

compile_trypath(common, rootbacktrack.cc, ccend, &rootbacktrack);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
  {
  sljit_free_compiler(compiler);
  SLJIT_FREE(common->localptrs);
  return;
  }

empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
empty_match_found = LABEL();

common->acceptlabel = LABEL();
if (common->accept != NULL)
  set_jumps(common->accept, common->acceptlabel);

/* This means we have a match. Update the ovector. */
copy_ovector(common, re->top_bracket + 1);
common->leavelabel = LABEL();
if (common->leave != NULL)
  set_jumps(common->leave, common->leavelabel);
sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);

if (mode != JIT_COMPILE)
  {
  common->partialmatchlabel = LABEL();
  set_jumps(common->partialmatch, common->partialmatchlabel);
  return_with_partial_match(common, common->leavelabel);
  }

empty_match_backtrack = LABEL();
compile_backtrackpath(common, rootbacktrack.top);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
  {
  sljit_free_compiler(compiler);
  SLJIT_FREE(common->localptrs);
  return;
  }

SLJIT_ASSERT(rootbacktrack.prev == NULL);

if (mode == JIT_PARTIAL_SOFT_COMPILE)
  {
  /* Update hit_start only in the first time. */
  jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0);
  JUMPHERE(jump);
  }

/* Check we have remaining characters. */
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));

if ((re->options & PCRE_ANCHORED) == 0)
  {
  if ((re->options & PCRE_FIRSTLINE) == 0)
    {
    if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
      {
      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1));
      CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);
      }
    else
      CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
    }
  else
    {
    SLJIT_ASSERT(common->first_line_end != 0);
    if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
      {
      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1));
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);
      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);
      JUMPTO(SLJIT_C_ZERO, mainloop);
      }
    else
      CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, mainloop);
    }
  }

/* No more remaining characters. */
if (reqbyte_notfound != NULL)
  JUMPHERE(reqbyte_notfound);

if (mode == JIT_PARTIAL_SOFT_COMPILE)
  CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0, common->partialmatchlabel);

OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
JUMPTO(SLJIT_JUMP, common->leavelabel);

flush_stubs(common);

JUMPHERE(empty_match);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack);
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found);
JUMPTO(SLJIT_JUMP, empty_match_backtrack);

common->currententry = common->entries;
while (common->currententry != NULL)
  {
  /* Might add new entries. */
  compile_recurse(common);
  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
    {
    sljit_free_compiler(compiler);
    SLJIT_FREE(common->localptrs);
    return;
    }
  flush_stubs(common);
  common->currententry = common->currententry->next;
  }

/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
/* This is a (really) rare case. */
set_jumps(common->stackalloc, LABEL());
/* RETURN_ADDR is not a saved register. */
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);

sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);

/* Allocation failed. */
JUMPHERE(jump);
/* We break the return address cache here, but this is a really rare case. */
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
JUMPTO(SLJIT_JUMP, common->leavelabel);

/* Call limit reached. */
set_jumps(common->calllimit, LABEL());
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
JUMPTO(SLJIT_JUMP, common->leavelabel);

if (common->revertframes != NULL)
  {
  set_jumps(common->revertframes, LABEL());
  do_revertframes(common);
  }
if (common->wordboundary != NULL)
  {
  set_jumps(common->wordboundary, LABEL());
  check_wordboundary(common);
  }
if (common->anynewline != NULL)
  {
  set_jumps(common->anynewline, LABEL());
  check_anynewline(common);
  }
if (common->hspace != NULL)
  {
  set_jumps(common->hspace, LABEL());
  check_hspace(common);
  }
if (common->vspace != NULL)
  {
  set_jumps(common->vspace, LABEL());
  check_vspace(common);
  }
if (common->casefulcmp != NULL)
  {
  set_jumps(common->casefulcmp, LABEL());
  do_casefulcmp(common);
  }
if (common->caselesscmp != NULL)
  {
  set_jumps(common->caselesscmp, LABEL());
  do_caselesscmp(common);
  }
#ifdef SUPPORT_UTF
if (common->utfreadchar != NULL)
  {
  set_jumps(common->utfreadchar, LABEL());
  do_utfreadchar(common);
  }
#ifdef COMPILE_PCRE8
if (common->utfreadtype8 != NULL)
  {
  set_jumps(common->utfreadtype8, LABEL());
  do_utfreadtype8(common);
  }
#endif
#endif /* COMPILE_PCRE8 */
#ifdef SUPPORT_UCP
if (common->getucd != NULL)
  {
  set_jumps(common->getucd, LABEL());
  do_getucd(common);
  }
#endif

SLJIT_FREE(common->localptrs);
executable_func = sljit_generate_code(compiler);
executable_size = sljit_get_generated_code_size(compiler);
sljit_free_compiler(compiler);
if (executable_func == NULL)
  return;

/* Reuse the function descriptor if possible. */
if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
  functions = (executable_functions *)extra->executable_jit;
else
  {
  functions = SLJIT_MALLOC(sizeof(executable_functions));
  if (functions == NULL)
    {
    /* This case is highly unlikely since we just recently
    freed a lot of memory. Although not impossible. */
    sljit_free_code(executable_func);
    return;
    }
  memset(functions, 0, sizeof(executable_functions));
  extra->executable_jit = functions;
  extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
  }

functions->executable_funcs[mode] = executable_func;
functions->executable_sizes[mode] = executable_size;
}

static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func)
{
union {
   void* executable_func;
   jit_function call_executable_func;
} convert_executable_func;
pcre_uint8 local_area[LOCAL_SPACE_SIZE];
struct sljit_stack local_stack;

local_stack.top = (sljit_w)&local_area;
local_stack.base = local_stack.top;
local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;
local_stack.max_limit = local_stack.limit;
arguments->stack = &local_stack;
convert_executable_func.executable_func = executable_func;
return convert_executable_func.call_executable_func(arguments);
}

int
PRIV(jit_exec)(const REAL_PCRE *re, const PUBL(extra) *extra_data, const pcre_uchar *subject,
  int length, int start_offset, int options, int *offsets, int offsetcount)
{
executable_functions *functions = (executable_functions *)extra_data->executable_jit;
union {
   void* executable_func;
   jit_function call_executable_func;
} convert_executable_func;
jit_arguments arguments;
int maxoffsetcount;
int retval;
int mode = JIT_COMPILE;

if ((options & PCRE_PARTIAL_HARD) != 0)
  mode = JIT_PARTIAL_HARD_COMPILE;
else if ((options & PCRE_PARTIAL_SOFT) != 0)
  mode = JIT_PARTIAL_SOFT_COMPILE;

if (functions->executable_funcs[mode] == NULL)
  return PCRE_ERROR_NULL;

/* Sanity checks should be handled by PCREXEC8. */
arguments.stack = NULL;
arguments.str = subject + start_offset;
arguments.begin = subject;
arguments.end = subject + length;
arguments.mark_ptr = NULL;
/* JIT decreases this value less frequently than the interpreter. */
arguments.calllimit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit;
arguments.notbol = (options & PCRE_NOTBOL) != 0;
arguments.noteol = (options & PCRE_NOTEOL) != 0;
arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
arguments.offsets = offsets;

/* PCREXEC8() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
the output vector for storing captured strings, with the remainder used as
workspace. We don't need the workspace here. For compatibility, we limit the
number of captured strings in the same way as PCREXEC8(), so that the user
gets the same result with and without JIT. */

if (offsetcount != 2)
  offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3;
maxoffsetcount = (re->top_bracket + 1) * 2;
if (offsetcount > maxoffsetcount)
  offsetcount = maxoffsetcount;
arguments.offsetcount = offsetcount;

if (functions->callback)
  arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata);
else
  arguments.stack = (struct sljit_stack *)functions->userdata;

if (arguments.stack == NULL)
  retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]);
else
  {
  convert_executable_func.executable_func = functions->executable_funcs[mode];
  retval = convert_executable_func.call_executable_func(&arguments);
  }

if (retval * 2 > offsetcount)
  retval = 0;
if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
  *(extra_data->mark) = arguments.mark_ptr;

return retval;
}

void
PRIV(jit_free)(void *executable_funcs)
{
int i;
executable_functions *functions = (executable_functions *)executable_funcs;
for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
  {
  if (functions->executable_funcs[i] != NULL)
    sljit_free_code(functions->executable_funcs[i]);
  }
SLJIT_FREE(functions);
}

int
PRIV(jit_get_size)(void *executable_funcs)
{
int i;
sljit_uw size = 0;
sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes;
for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
  size += executable_sizes[i];
return (int)size;
}

const char*
PRIV(jit_get_target)(void)
{
return sljit_get_platform_name();
}

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL pcre_jit_stack *
pcre_jit_stack_alloc(int startsize, int maxsize)
#else
PCRE_EXP_DECL pcre16_jit_stack *
pcre16_jit_stack_alloc(int startsize, int maxsize)
#endif
{
if (startsize < 1 || maxsize < 1)
  return NULL;
if (startsize > maxsize)
  startsize = maxsize;
startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize);
}

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL void
pcre_jit_stack_free(pcre_jit_stack *stack)
#else
PCRE_EXP_DECL void
pcre16_jit_stack_free(pcre16_jit_stack *stack)
#endif
{
sljit_free_stack((struct sljit_stack *)stack);
}

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL void
pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
#else
PCRE_EXP_DECL void
pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
#endif
{
executable_functions *functions;
if (extra != NULL &&
    (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
    extra->executable_jit != NULL)
  {
  functions = (executable_functions *)extra->executable_jit;
  functions->callback = callback;
  functions->userdata = userdata;
  }
}

#else  /* SUPPORT_JIT */

/* These are dummy functions to avoid linking errors when JIT support is not
being compiled. */

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL pcre_jit_stack *
pcre_jit_stack_alloc(int startsize, int maxsize)
#else
PCRE_EXP_DECL pcre16_jit_stack *
pcre16_jit_stack_alloc(int startsize, int maxsize)
#endif
{
(void)startsize;
(void)maxsize;
return NULL;
}

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL void
pcre_jit_stack_free(pcre_jit_stack *stack)
#else
PCRE_EXP_DECL void
pcre16_jit_stack_free(pcre16_jit_stack *stack)
#endif
{
(void)stack;
}

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL void
pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
#else
PCRE_EXP_DECL void
pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
#endif
{
(void)extra;
(void)callback;
(void)userdata;
}

#endif

/* End of JITCOMP8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_jit_compile.c converted to JITCOMP8*/
/*autoconv-0010 JITCOMP8 line: 44 added HAVE_CONFIG_H*/
/*autoconv-0011 JITCOMP8 line: 47 config.h replaced by CONFIG.h*/
/*autoconv-0011 JITCOMP8 line: 50 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 JITCOMP8 line: 7288 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 JITCOMP8 line: 7302 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 JITCOMP8 line: 7305 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 JITCOMP8 line: 7457 pcre_jit_compile replaced by JITCOMP8*/
./ ADD NAME=BYTEORD8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains an internal function that tests a compiled pattern to
see if it was compiled with the opposite endianness. If so, it uses an
auxiliary local function to flip the appropriate bytes. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"


/*************************************************
*             Swap byte functions                *
*************************************************/

/* The following functions swap the bytes of a pcre_uint16
and pcre_uint32 value.

Arguments:
  value        any number

Returns:       the byte swapped value
*/

static pcre_uint32
swap_uint32(pcre_uint32 value)
{
return ((value & 0x000000ff) << 24) |
       ((value & 0x0000ff00) <<  8) |
       ((value & 0x00ff0000) >>  8) |
       (value >> 24);
}

static pcre_uint16
swap_uint16(pcre_uint16 value)
{
return (value >> 8) | (value << 8);
}


/*************************************************
*       Test for a byte-flipped compiled regex   *
*************************************************/

/* This function swaps the bytes of a compiled pattern usually
loaded form the disk. It also sets the tables pointer, which
is likely an invalid pointer after reload.

Arguments:
  argument_re     points to the compiled expression
  extra_data      points to extra data or is NULL
  tables          points to the character tables or NULL

Returns:          0 if the swap is successful, negative on error
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
  pcre_extra *extra_data, const unsigned char *tables)
#else
PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
  pcre16_extra *extra_data, const unsigned char *tables)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)argument_re;
pcre_study_data *study;
#ifndef COMPILE_PCRE8
pcre_uchar *ptr;
int length;
#ifdef SUPPORT_UTF
BOOL utf;
BOOL utf16_char;
#endif /* SUPPORT_UTF */
#endif /* !COMPILE_PCRE8 */

if (re == NULL) return PCRE_ERROR_NULL;
if (re->magic_number == MAGIC_NUMBER)
  {
  if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
  re->tables = tables;
  return 0;
  }

if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
if ((swap_uint16(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;

re->magic_number = MAGIC_NUMBER;
re->size = swap_uint32(re->size);
re->options = swap_uint32(re->options);
re->flags = swap_uint16(re->flags);
re->top_bracket = swap_uint16(re->top_bracket);
re->top_backref = swap_uint16(re->top_backref);
re->first_char = swap_uint16(re->first_char);
re->req_char = swap_uint16(re->req_char);
re->name_table_offset = swap_uint16(re->name_table_offset);
re->name_entry_size = swap_uint16(re->name_entry_size);
re->name_count = swap_uint16(re->name_count);
re->ref_count = swap_uint16(re->ref_count);
re->tables = tables;

if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
  {
  study = (pcre_study_data *)extra_data->study_data;
  study->size = swap_uint32(study->size);
  study->flags = swap_uint32(study->flags);
  study->minlength = swap_uint32(study->minlength);
  }

#ifndef COMPILE_PCRE8
ptr = (pcre_uchar *)re + re->name_table_offset;
length = re->name_count * re->name_entry_size;
#ifdef SUPPORT_UTF
utf = (re->options & PCRE_UTF16) != 0;
utf16_char = FALSE;
#endif

while(TRUE)
  {
  /* Swap previous characters. */
  while (length-- > 0)
    {
    *ptr = swap_uint16(*ptr);
    ptr++;
    }
#ifdef SUPPORT_UTF
  if (utf16_char)
    {
    if (HAS_EXTRALEN(ptr[-1]))
      {
      /* We know that there is only one extra character in UTF-16. */
      *ptr = swap_uint16(*ptr);
      ptr++;
      }
    }
  utf16_char = FALSE;
#endif /* SUPPORT_UTF */

  /* Get next opcode. */
  length = 0;
  *ptr = swap_uint16(*ptr);
  switch (*ptr)
    {
    case OP_END:
    return 0;

#ifdef SUPPORT_UTF
    case OP_CHAR:
    case OP_CHARI:
    case OP_NOT:
    case OP_NOTI:
    case OP_STAR:
    case OP_MINSTAR:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_QUERY:
    case OP_MINQUERY:
    case OP_UPTO:
    case OP_MINUPTO:
    case OP_EXACT:
    case OP_POSSTAR:
    case OP_POSPLUS:
    case OP_POSQUERY:
    case OP_POSUPTO:
    case OP_STARI:
    case OP_MINSTARI:
    case OP_PLUSI:
    case OP_MINPLUSI:
    case OP_QUERYI:
    case OP_MINQUERYI:
    case OP_UPTOI:
    case OP_MINUPTOI:
    case OP_EXACTI:
    case OP_POSSTARI:
    case OP_POSPLUSI:
    case OP_POSQUERYI:
    case OP_POSUPTOI:
    case OP_NOTSTAR:
    case OP_NOTMINSTAR:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTQUERY:
    case OP_NOTMINQUERY:
    case OP_NOTUPTO:
    case OP_NOTMINUPTO:
    case OP_NOTEXACT:
    case OP_NOTPOSSTAR:
    case OP_NOTPOSPLUS:
    case OP_NOTPOSQUERY:
    case OP_NOTPOSUPTO:
    case OP_NOTSTARI:
    case OP_NOTMINSTARI:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUSI:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERYI:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTOI:
    case OP_NOTEXACTI:
    case OP_NOTPOSSTARI:
    case OP_NOTPOSPLUSI:
    case OP_NOTPOSQUERYI:
    case OP_NOTPOSUPTOI:
    if (utf) utf16_char = TRUE;
#endif
    /* Fall through. */

    default:
    length = PRIV(OP_lengths)[*ptr] - 1;
    break;

    case OP_CLASS:
    case OP_NCLASS:
    /* Skip the character bit map. */
    ptr += 32/sizeof(pcre_uchar);
    length = 0;
    break;

    case OP_XCLASS:
    /* Reverse the size of the XCLASS instance. */
    ptr++;
    *ptr = swap_uint16(*ptr);
    if (LINK_SIZE > 1)
      {
      /* LINK_SIZE can be 1 or 2 in 16 bit mode. */
      ptr++;
      *ptr = swap_uint16(*ptr);
      }
    ptr++;
    length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
    *ptr = swap_uint16(*ptr);
    if ((*ptr & XCL_MAP) != 0)
      {
      /* Skip the character bit map. */
      ptr += 32/sizeof(pcre_uchar);
      length -= 32/sizeof(pcre_uchar);
      }
    break;
    }
  ptr++;
  }
/* Control should never reach here in 16 bit mode. */
#endif /* !COMPILE_PCRE8 */

return 0;
}

/* End of BYTEORD8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_byte_order.c converted to BYTEORD8*/
/*autoconv-0010 BYTEORD8 line: 47 added HAVE_CONFIG_H*/
/*autoconv-0011 BYTEORD8 line: 50 config.h replaced by CONFIG.h*/
/*autoconv-0011 BYTEORD8 line: 53 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 BYTEORD8 line: 291 pcre_byte_order replaced by BYTEORD8*/
./ ADD NAME=PCRE 
/*************************************************
*       Perl-Compatible Regular Expressions      *
*************************************************/

/* This is the public header file for the PCRE library, to be #included by
applications that call the PCRE functions.

           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

/* This pcre.h was generated manually from pcre.h.grnrric for native z/OS.
Version 0.1
Changes by Ze'ev Atlas 2012. 
No changes applied as of yet.*/

#ifndef _PCRE_H
#define _PCRE_H

/* The current PCRE version information. */

#define PCRE_MAJOR          8
#define PCRE_MINOR          31
#define PCRE_PRERELEASE     
#define PCRE_DATE           2012-07-06

/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
export setting is defined in pcre_internal.h, which includes this file. So we
don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */

#if defined(_WIN32) && !defined(PCRE_STATIC)
#  ifndef PCRE_EXP_DECL
#    define PCRE_EXP_DECL  extern __declspec(dllimport)
#  endif
#  ifdef __cplusplus
#    ifndef PCRECPP_EXP_DECL
#      define PCRECPP_EXP_DECL  extern __declspec(dllimport)
#    endif
#    ifndef PCRECPP_EXP_DEFN
#      define PCRECPP_EXP_DEFN  __declspec(dllimport)
#    endif
#  endif
#endif

/* By default, we use the standard "extern" declarations. */

#ifndef PCRE_EXP_DECL
#  ifdef __cplusplus
#    define PCRE_EXP_DECL  extern "C"
#  else
#    define PCRE_EXP_DECL  extern
#  endif
#endif

#ifdef __cplusplus
#  ifndef PCRECPP_EXP_DECL
#    define PCRECPP_EXP_DECL  extern
#  endif
#  ifndef PCRECPP_EXP_DEFN
#    define PCRECPP_EXP_DEFN
#  endif
#endif

/* Have to include stdlib.h in order to ensure that size_t is defined;
it is needed here for malloc. */

#include <stdlib.h>

/* Allow for C++ users */

#ifdef __cplusplus
extern "C" {
#endif

/* Options. Some are compile-time only, some are run-time only, and some are
both, so we keep them all distinct. However, almost all the bits in the options
word are now used. In the long run, we may have to re-use some of the
compile-time only bits for runtime options, or vice versa. In the comments
below, "compile", "exec", and "DFA exec" mean that the option is permitted to
be set for those functions; "used in" means that an option may be set only for
compile, but is subsequently referenced in exec and/or DFA exec. Any of the
compile-time options may be inspected during studying (and therefore JIT
compiling). */

#define PCRE_CASELESS           0x00000001  /* Compile */
#define PCRE_MULTILINE          0x00000002  /* Compile */
#define PCRE_DOTALL             0x00000004  /* Compile */
#define PCRE_EXTENDED           0x00000008  /* Compile */
#define PCRE_ANCHORED           0x00000010  /* Compile, exec, DFA exec */
#define PCRE_DOLLAR_ENDONLY     0x00000020  /* Compile, used in exec, DFA exec */
#define PCRE_EXTRA              0x00000040  /* Compile */
#define PCRE_NOTBOL             0x00000080  /* Exec, DFA exec */
#define PCRE_NOTEOL             0x00000100  /* Exec, DFA exec */
#define PCRE_UNGREEDY           0x00000200  /* Compile */
#define PCRE_NOTEMPTY           0x00000400  /* Exec, DFA exec */
/* The next two are also used in exec and DFA exec */
#define PCRE_UTF8               0x00000800  /* Compile (same as PCRE_UTF16) */
#define PCRE_UTF16              0x00000800  /* Compile (same as PCRE_UTF8) */
#define PCRE_NO_AUTO_CAPTURE    0x00001000  /* Compile */
/* The next two are also used in exec and DFA exec */
#define PCRE_NO_UTF8_CHECK      0x00002000  /* Compile (same as PCRE_NO_UTF16_CHECK) */
#define PCRE_NO_UTF16_CHECK     0x00002000  /* Compile (same as PCRE_NO_UTF8_CHECK) */
#define PCRE_AUTO_CALLOUT       0x00004000  /* Compile */
#define PCRE_PARTIAL_SOFT       0x00008000  /* Exec, DFA exec */
#define PCRE_PARTIAL            0x00008000  /* Backwards compatible synonym */
#define PCRE_DFA_SHORTEST       0x00010000  /* DFA exec */
#define PCRE_DFA_RESTART        0x00020000  /* DFA exec */
#define PCRE_FIRSTLINE          0x00040000  /* Compile, used in exec, DFA exec */
#define PCRE_DUPNAMES           0x00080000  /* Compile */
#define PCRE_NEWLINE_CR         0x00100000  /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_LF         0x00200000  /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_CRLF       0x00300000  /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_ANY        0x00400000  /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_ANYCRLF    0x00500000  /* Compile, exec, DFA exec */
#define PCRE_BSR_ANYCRLF        0x00800000  /* Compile, exec, DFA exec */
#define PCRE_BSR_UNICODE        0x01000000  /* Compile, exec, DFA exec */
#define PCRE_JAVASCRIPT_COMPAT  0x02000000  /* Compile, used in exec */
#define PCRE_NO_START_OPTIMIZE  0x04000000  /* Compile, exec, DFA exec */
#define PCRE_NO_START_OPTIMISE  0x04000000  /* Synonym */
#define PCRE_PARTIAL_HARD       0x08000000  /* Exec, DFA exec */
#define PCRE_NOTEMPTY_ATSTART   0x10000000  /* Exec, DFA exec */
#define PCRE_UCP                0x20000000  /* Compile, used in exec, DFA exec */

/* Exec-time and get/set-time error codes */

#define PCRE_ERROR_NOMATCH          (-1)
#define PCRE_ERROR_NULL             (-2)
#define PCRE_ERROR_BADOPTION        (-3)
#define PCRE_ERROR_BADMAGIC         (-4)
#define PCRE_ERROR_UNKNOWN_OPCODE   (-5)
#define PCRE_ERROR_UNKNOWN_NODE     (-5)  /* For backward compatibility */
#define PCRE_ERROR_NOMEMORY         (-6)
#define PCRE_ERROR_NOSUBSTRING      (-7)
#define PCRE_ERROR_MATCHLIMIT       (-8)
#define PCRE_ERROR_CALLOUT          (-9)  /* Never used by PCRE itself */
#define PCRE_ERROR_BADUTF8         (-10)  /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16        (-10)  /* Same for 8/16 */
#define PCRE_ERROR_BADUTF8_OFFSET  (-11)  /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16_OFFSET (-11)  /* Same for 8/16 */
#define PCRE_ERROR_PARTIAL         (-12)
#define PCRE_ERROR_BADPARTIAL      (-13)
#define PCRE_ERROR_INTERNAL        (-14)
#define PCRE_ERROR_BADCOUNT        (-15)
#define PCRE_ERROR_DFA_UITEM       (-16)
#define PCRE_ERROR_DFA_UCOND       (-17)
#define PCRE_ERROR_DFA_UMLIMIT     (-18)
#define PCRE_ERROR_DFA_WSSIZE      (-19)
#define PCRE_ERROR_DFA_RECURSE     (-20)
#define PCRE_ERROR_RECURSIONLIMIT  (-21)
#define PCRE_ERROR_NULLWSLIMIT     (-22)  /* No longer actually used */
#define PCRE_ERROR_BADNEWLINE      (-23)
#define PCRE_ERROR_BADOFFSET       (-24)
#define PCRE_ERROR_SHORTUTF8       (-25)
#define PCRE_ERROR_SHORTUTF16      (-25)  /* Same for 8/16 */
#define PCRE_ERROR_RECURSELOOP     (-26)
#define PCRE_ERROR_JIT_STACKLIMIT  (-27)
#define PCRE_ERROR_BADMODE         (-28)
#define PCRE_ERROR_BADENDIANNESS   (-29)
#define PCRE_ERROR_DFA_BADRESTART  (-30)

/* Specific error codes for UTF-8 validity checks */

#define PCRE_UTF8_ERR0               0
#define PCRE_UTF8_ERR1               1
#define PCRE_UTF8_ERR2               2
#define PCRE_UTF8_ERR3               3
#define PCRE_UTF8_ERR4               4
#define PCRE_UTF8_ERR5               5
#define PCRE_UTF8_ERR6               6
#define PCRE_UTF8_ERR7               7
#define PCRE_UTF8_ERR8               8
#define PCRE_UTF8_ERR9               9
#define PCRE_UTF8_ERR10             10
#define PCRE_UTF8_ERR11             11
#define PCRE_UTF8_ERR12             12
#define PCRE_UTF8_ERR13             13
#define PCRE_UTF8_ERR14             14
#define PCRE_UTF8_ERR15             15
#define PCRE_UTF8_ERR16             16
#define PCRE_UTF8_ERR17             17
#define PCRE_UTF8_ERR18             18
#define PCRE_UTF8_ERR19             19
#define PCRE_UTF8_ERR20             20
#define PCRE_UTF8_ERR21             21

/* Specific error codes for UTF-16 validity checks */

#define PCRE_UTF16_ERR0              0
#define PCRE_UTF16_ERR1              1
#define PCRE_UTF16_ERR2              2
#define PCRE_UTF16_ERR3              3
#define PCRE_UTF16_ERR4              4

/* Request types for FULLINF8() */

#define PCRE_INFO_OPTIONS            0
#define PCRE_INFO_SIZE               1
#define PCRE_INFO_CAPTURECOUNT       2
#define PCRE_INFO_BACKREFMAX         3
#define PCRE_INFO_FIRSTBYTE          4
#define PCRE_INFO_FIRSTCHAR          4  /* For backwards compatibility */
#define PCRE_INFO_FIRSTTABLE         5
#define PCRE_INFO_LASTLITERAL        6
#define PCRE_INFO_NAMEENTRYSIZE      7
#define PCRE_INFO_NAMECOUNT          8
#define PCRE_INFO_NAMETABLE          9
#define PCRE_INFO_STUDYSIZE         10
#define PCRE_INFO_DEFAULT_TABLES    11
#define PCRE_INFO_OKPARTIAL         12
#define PCRE_INFO_JCHANGED          13
#define PCRE_INFO_HASCRORLF         14
#define PCRE_INFO_MINLENGTH         15
#define PCRE_INFO_JIT               16
#define PCRE_INFO_JITSIZE           17
#define PCRE_INFO_MAXLOOKBEHIND     18

/* Request types for CONFIG8(). Do not re-arrange, in order to remain
compatible. */

#define PCRE_CONFIG_UTF8                    0
#define PCRE_CONFIG_NEWLINE                 1
#define PCRE_CONFIG_LINK_SIZE               2
#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD  3
#define PCRE_CONFIG_MATCH_LIMIT             4
#define PCRE_CONFIG_STACKRECURSE            5
#define PCRE_CONFIG_UNICODE_PROPERTIES      6
#define PCRE_CONFIG_MATCH_LIMIT_RECURSION   7
#define PCRE_CONFIG_BSR                     8
#define PCRE_CONFIG_JIT                     9
#define PCRE_CONFIG_UTF16                  10
#define PCRE_CONFIG_JITTARGET              11

/* Request types for STUDY8(). Do not re-arrange, in order to remain
compatible. */

#define PCRE_STUDY_JIT_COMPILE                0x0001
#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE   0x0002
#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE   0x0004
#define PCRE_STUDY_EXTRA_NEEDED               0x0008

/* Bit flags for the pcre[16]_extra structure. Do not re-arrange or redefine
these bits, just add new ones on the end, in order to remain compatible. */

#define PCRE_EXTRA_STUDY_DATA             0x0001
#define PCRE_EXTRA_MATCH_LIMIT            0x0002
#define PCRE_EXTRA_CALLOUT_DATA           0x0004
#define PCRE_EXTRA_TABLES                 0x0008
#define PCRE_EXTRA_MATCH_LIMIT_RECURSION  0x0010
#define PCRE_EXTRA_MARK                   0x0020
#define PCRE_EXTRA_EXECUTABLE_JIT         0x0040

/* Types */

struct real_pcre;                 /* declaration; the definition is private  */
typedef struct real_pcre pcre;

struct real_pcre16;               /* declaration; the definition is private  */
typedef struct real_pcre16 pcre16;

struct real_pcre_jit_stack;       /* declaration; the definition is private  */
typedef struct real_pcre_jit_stack pcre_jit_stack;

struct real_pcre16_jit_stack;     /* declaration; the definition is private  */
typedef struct real_pcre16_jit_stack pcre16_jit_stack;

/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain
a 16 bit wide signed data type. Otherwise it can be a dummy data type since
pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */
#ifndef PCRE_UCHAR16
#define PCRE_UCHAR16 unsigned short
#endif

#ifndef PCRE_SPTR16
#define PCRE_SPTR16 const PCRE_UCHAR16 *
#endif

/* When PCRE is compiled as a C++ library, the subject pointer type can be
replaced with a custom type. For conventional use, the public interface is a
const char *. */

#ifndef PCRE_SPTR
#define PCRE_SPTR const char *
#endif

/* The structure for passing additional data to PCREXEC8(). This is defined in
such as way as to be extensible. Always add new fields at the end, in order to
remain compatible. */

typedef struct pcre_extra {
  unsigned long int flags;        /* Bits for which fields are set */
  void *study_data;               /* Opaque data from STUDY8() */
  unsigned long int match_limit;  /* Maximum number of calls to match() */
  void *callout_data;             /* Data passed back in callouts */
  const unsigned char *tables;    /* Pointer to character tables */
  unsigned long int match_limit_recursion; /* Max recursive calls to match() */
  unsigned char **mark;           /* For passing back a mark pointer */
  void *executable_jit;           /* Contains a pointer to a compiled jit code */
} pcre_extra;

/* Same structure as above, but with 16 bit char pointers. */

typedef struct pcre16_extra {
  unsigned long int flags;        /* Bits for which fields are set */
  void *study_data;               /* Opaque data from STUDY8() */
  unsigned long int match_limit;  /* Maximum number of calls to match() */
  void *callout_data;             /* Data passed back in callouts */
  const unsigned char *tables;    /* Pointer to character tables */
  unsigned long int match_limit_recursion; /* Max recursive calls to match() */
  PCRE_UCHAR16 **mark;            /* For passing back a mark pointer */
  void *executable_jit;           /* Contains a pointer to a compiled jit code */
} pcre16_extra;

/* The structure for passing out data via the pcre_callout_function. We use a
structure so that new fields can be added on the end in future versions,
without changing the API of the function, thereby allowing old clients to work
without modification. */

typedef struct pcre_callout_block {
  int          version;           /* Identifies version of block */
  /* ------------------------ Version 0 ------------------------------- */
  int          callout_number;    /* Number compiled into pattern */
  int         *offset_vector;     /* The offset vector */
  PCRE_SPTR    subject;           /* The subject being matched */
  int          subject_length;    /* The length of the subject */
  int          start_match;       /* Offset to start of this match attempt */
  int          current_position;  /* Where we currently are in the subject */
  int          capture_top;       /* Max current capture */
  int          capture_last;      /* Most recently closed capture */
  void        *callout_data;      /* Data passed in with the call */
  /* ------------------- Added for Version 1 -------------------------- */
  int          pattern_position;  /* Offset to next item in the pattern */
  int          next_item_length;  /* Length of next item in the pattern */
  /* ------------------- Added for Version 2 -------------------------- */
  const unsigned char *mark;      /* Pointer to current mark or NULL    */
  /* ------------------------------------------------------------------ */
} pcre_callout_block;

/* Same structure as above, but with 16 bit char pointers. */

typedef struct pcre16_callout_block {
  int          version;           /* Identifies version of block */
  /* ------------------------ Version 0 ------------------------------- */
  int          callout_number;    /* Number compiled into pattern */
  int         *offset_vector;     /* The offset vector */
  PCRE_SPTR16  subject;           /* The subject being matched */
  int          subject_length;    /* The length of the subject */
  int          start_match;       /* Offset to start of this match attempt */
  int          current_position;  /* Where we currently are in the subject */
  int          capture_top;       /* Max current capture */
  int          capture_last;      /* Most recently closed capture */
  void        *callout_data;      /* Data passed in with the call */
  /* ------------------- Added for Version 1 -------------------------- */
  int          pattern_position;  /* Offset to next item in the pattern */
  int          next_item_length;  /* Length of next item in the pattern */
  /* ------------------- Added for Version 2 -------------------------- */
  const PCRE_UCHAR16 *mark;       /* Pointer to current mark or NULL    */
  /* ------------------------------------------------------------------ */
} pcre16_callout_block;

/* Indirection for store get and free functions. These can be set to
alternative malloc/free functions if required. Special ones are used in the
non-recursive case for "frames". There is also an optional callout function
that is triggered by the (?) regex item. For Virtual Pascal, these definitions
have to take another form. */

#ifndef VPCOMPAT
PCRE_EXP_DECL void *(*pcre_malloc)(size_t);
PCRE_EXP_DECL void  (*pcre_free)(void *);
PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
PCRE_EXP_DECL void  (*pcre_stack_free)(void *);
PCRE_EXP_DECL int   (*pcre_callout)(pcre_callout_block *);

PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
PCRE_EXP_DECL void  (*pcre16_free)(void *);
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
PCRE_EXP_DECL void  (*pcre16_stack_free)(void *);
PCRE_EXP_DECL int   (*pcre16_callout)(pcre16_callout_block *);
#else   /* VPCOMPAT */
PCRE_EXP_DECL void *pcre_malloc(size_t);
PCRE_EXP_DECL void  pcre_free(void *);
PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
PCRE_EXP_DECL void  pcre_stack_free(void *);
PCRE_EXP_DECL int   pcre_callout(pcre_callout_block *);

PCRE_EXP_DECL void *pcre16_malloc(size_t);
PCRE_EXP_DECL void  pcre16_free(void *);
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
PCRE_EXP_DECL void  pcre16_stack_free(void *);
PCRE_EXP_DECL int   pcre16_callout(pcre16_callout_block *);
#endif  /* VPCOMPAT */

/* User defined callback which provides a stack just before the match starts. */

typedef pcre_jit_stack *(*pcre_jit_callback)(void *);
typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *);

/* Exported PCRE functions */

PCRE_EXP_DECL pcre *COMPILE8(const char *, int, const char **, int *,
                  const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *,
                  const unsigned char *);
PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
                  int *, const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **,
                  int *, const unsigned char *);
PCRE_EXP_DECL int  CONFIG8(int, void *);
PCRE_EXP_DECL int  pcre16_config(int, void *);
PCRE_EXP_DECL int  pcre_copy_named_substring(const pcre *, const char *,
                  int *, int, const char *, char *, int);
PCRE_EXP_DECL int  pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16,
                  int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int  pcre_copy_substring(const char *, int *, int, int,
                  char *, int);
PCRE_EXP_DECL int  pcre16_copy_substring(PCRE_SPTR16, int *, int, int,
                  PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int  DFAEXEC8(const pcre *, const pcre_extra *,
                  const char *, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int  pcre16_dfa_exec(const pcre16 *, const pcre16_extra *,
                  PCRE_SPTR16, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int  PCREXEC8(const pcre *, const pcre_extra *, PCRE_SPTR,
                   int, int, int, int *, int);
PCRE_EXP_DECL int  pcre16_exec(const pcre16 *, const pcre16_extra *,
                   PCRE_SPTR16, int, int, int, int *, int);
PCRE_EXP_DECL void pcre_free_substring(const char *);
PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
PCRE_EXP_DECL void pcre_free_substring_list(const char **);
PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
PCRE_EXP_DECL int  FULLINF8(const pcre *, const pcre_extra *, int,
                  void *);
PCRE_EXP_DECL int  pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int,
                  void *);
PCRE_EXP_DECL int  pcre_get_named_substring(const pcre *, const char *,
                  int *, int, const char *, const char **);
PCRE_EXP_DECL int  pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16,
                  int *, int, PCRE_SPTR16, PCRE_SPTR16 *);
PCRE_EXP_DECL int  pcre_get_stringnumber(const pcre *, const char *);
PCRE_EXP_DECL int  pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
PCRE_EXP_DECL int  pcre_get_stringtable_entries(const pcre *, const char *,
                  char **, char **);
PCRE_EXP_DECL int  pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16,
                  PCRE_UCHAR16 **, PCRE_UCHAR16 **);
PCRE_EXP_DECL int  pcre_get_substring(const char *, int *, int, int,
                  const char **);
PCRE_EXP_DECL int  pcre16_get_substring(PCRE_SPTR16, int *, int, int,
                  PCRE_SPTR16 *);
PCRE_EXP_DECL int  pcre_get_substring_list(const char *, int *, int,
                  const char ***);
PCRE_EXP_DECL int  pcre16_get_substring_list(PCRE_SPTR16, int *, int,
                  PCRE_SPTR16 **);
PCRE_EXP_DECL const unsigned char *MAKETAB8(void);
PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
PCRE_EXP_DECL int  REFCOUN8(pcre *, int);
PCRE_EXP_DECL int  pcre16_refcount(pcre16 *, int);
PCRE_EXP_DECL pcre_extra *STUDY8(const pcre *, int, const char **);
PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **);
PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
PCRE_EXP_DECL const char *VERSION8(void);
PCRE_EXP_DECL const char *pcre16_version(void);

/* Utility functions for byte order swaps. */
PCRE_EXP_DECL int  pcre_pattern_to_host_byte_order(pcre *, pcre_extra *,
                  const unsigned char *);
PCRE_EXP_DECL int  pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *,
                  const unsigned char *);
PCRE_EXP_DECL int  pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
                  PCRE_SPTR16, int, int *, int);

/* JIT compiler related functions. */

PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int);
PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *);
PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *);
PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *,
                  pcre_jit_callback, void *);
PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *,
                  pcre16_jit_callback, void *);

#ifdef __cplusplus
}  /* extern "C" */
#endif

#endif /* End of pcre.h */
/*autoconv-0001 C:\projects\pcreport\pcre.h converted to PCRE*/
/*autoconv-0013 PCRE line: 222 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRE line: 245 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRE line: 261 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCRE line: 313 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRE line: 319 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCRE line: 332 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCRE line: 427 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRE line: 435 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRE line: 445 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 PCRE line: 449 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRE line: 457 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRE line: 479 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0013 PCRE line: 481 pcre_refcount replaced by REFCOUN8*/
/*autoconv-0013 PCRE line: 483 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCRE line: 487 pcre_version replaced by VERSION8*/
./ ADD NAME=STUDY8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function STUDY8(), along with local
supporting functions. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7))

/* Returns from set_start_bits() */

enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN };



/*************************************************
*   Find the minimum subject length for a group  *
*************************************************/

/* Scan a parenthesized group and compute the minimum length of subject that
is needed to match it. This is a lower bound; it does not mean there is a
string of that length that matches. In UTF8 mode, the result is in characters
rather than bytes.

Arguments:
  code            pointer to start of group (the bracket)
  startcode       pointer to start of the whole pattern
  options         the compiling options
  int             RECURSE depth

Returns:   the minimum length
           -1 if \C in UTF-8 mode or (*ACCEPT) was encountered
           -2 internal error (missing capturing bracket)
           -3 internal error (opcode not listed)
*/

static int
find_minlength(const pcre_uchar *code, const pcre_uchar *startcode, int options,
  int recurse_depth)
{
int length = -1;
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
BOOL utf = (options & PCRE_UTF8) != 0;
BOOL had_recurse = FALSE;
register int branchlength = 0;
register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;

if (*code == OP_CBRA || *code == OP_SCBRA ||
    *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE;

/* Scan along the opcodes for this branch. If we get to the end of the
branch, check the length against that of the other branches. */

for (;;)
  {
  int d, min;
  pcre_uchar *cs, *ce;
  register int op = *cc;

  switch (op)
    {
    case OP_COND:
    case OP_SCOND:

    /* If there is only one branch in a condition, the implied branch has zero
    length, so we don't add anything. This covers the DEFINE "condition"
    automatically. */

    cs = cc + GET(cc, 1);
    if (*cs != OP_ALT)
      {
      cc = cs + 1 + LINK_SIZE;
      break;
      }

    /* Otherwise we can fall through and treat it the same as any other
    subpattern. */

    case OP_CBRA:
    case OP_SCBRA:
    case OP_BRA:
    case OP_SBRA:
    case OP_CBRAPOS:
    case OP_SCBRAPOS:
    case OP_BRAPOS:
    case OP_SBRAPOS:
    case OP_ONCE:
    case OP_ONCE_NC:
    d = find_minlength(cc, startcode, options, recurse_depth);
    if (d < 0) return d;
    branchlength += d;
    do cc += GET(cc, 1); while (*cc == OP_ALT);
    cc += 1 + LINK_SIZE;
    break;

    /* ACCEPT makes things far too complicated; we have to give up. */

    case OP_ACCEPT:
    case OP_ASSERT_ACCEPT:
    return -1;

    /* Reached end of a branch; if it's a ket it is the end of a nested
    call. If it's ALT it is an alternation in a nested call. If it is END it's
    the end of the outer call. All can be handled by the same code. If an
    ACCEPT was previously encountered, use the length that was in force at that
    time, and pass back the shortest ACCEPT length. */

    case OP_ALT:
    case OP_KET:
    case OP_KETRMAX:
    case OP_KETRMIN:
    case OP_KETRPOS:
    case OP_END:
    if (length < 0 || (!had_recurse && branchlength < length))
      length = branchlength;
    if (op != OP_ALT) return length;
    cc += 1 + LINK_SIZE;
    branchlength = 0;
    had_recurse = FALSE;
    break;

    /* Skip over assertive subpatterns */

    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    do cc += GET(cc, 1); while (*cc == OP_ALT);
    /* Fall through */

    /* Skip over things that don't match chars */

    case OP_REVERSE:
    case OP_CREF:
    case OP_NCREF:
    case OP_RREF:
    case OP_NRREF:
    case OP_DEF:
    case OP_CALLOUT:
    case OP_SOD:
    case OP_SOM:
    case OP_EOD:
    case OP_EODN:
    case OP_CIRC:
    case OP_CIRCM:
    case OP_DOLL:
    case OP_DOLLM:
    case OP_NOT_WORD_BOUNDARY:
    case OP_WORD_BOUNDARY:
    cc += PRIV(OP_lengths)[*cc];
    break;

    /* Skip over a subpattern that has a {0} or {0,x} quantifier */

    case OP_BRAZERO:
    case OP_BRAMINZERO:
    case OP_BRAPOSZERO:
    case OP_SKIPZERO:
    cc += PRIV(OP_lengths)[*cc];
    do cc += GET(cc, 1); while (*cc == OP_ALT);
    cc += 1 + LINK_SIZE;
    break;

    /* Handle literal characters and + repetitions */

    case OP_CHAR:
    case OP_CHARI:
    case OP_NOT:
    case OP_NOTI:
    case OP_PLUS:
    case OP_PLUSI:
    case OP_MINPLUS:
    case OP_MINPLUSI:
    case OP_POSPLUS:
    case OP_POSPLUSI:
    case OP_NOTPLUS:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUS:
    case OP_NOTMINPLUSI:
    case OP_NOTPOSPLUS:
    case OP_NOTPOSPLUSI:
    branchlength++;
    cc += 2;
#ifdef SUPPORT_UTF
    if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
    break;

    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEPOSPLUS:
    branchlength++;
    cc += (cc[1] == OP_PROP || cc[1] == OP_NOTPROP)? 4 : 2;
    break;

    /* Handle exact repetitions. The count is already in characters, but we
    need to skip over a multibyte character in UTF8 mode.  */

    case OP_EXACT:
    case OP_EXACTI:
    case OP_NOTEXACT:
    case OP_NOTEXACTI:
    branchlength += GET2(cc,1);
    cc += 2 + IMM2_SIZE;
#ifdef SUPPORT_UTF
    if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
    break;

    case OP_TYPEEXACT:
    branchlength += GET2(cc,1);
    cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP
      || cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);
    break;

    /* Handle single-char non-literal matchers */

    case OP_PROP:
    case OP_NOTPROP:
    cc += 2;
    /* Fall through */

    case OP_NOT_DIGIT:
    case OP_DIGIT:
    case OP_NOT_WHITESPACE:
    case OP_WHITESPACE:
    case OP_NOT_WORDCHAR:
    case OP_WORDCHAR:
    case OP_ANY:
    case OP_ALLANY:
    case OP_EXTUNI:
    case OP_HSPACE:
    case OP_NOT_HSPACE:
    case OP_VSPACE:
    case OP_NOT_VSPACE:
    branchlength++;
    cc++;
    break;

    /* "Any newline" might match two characters, but it also might match just
    one. */

    case OP_ANYNL:
    branchlength += 1;
    cc++;
    break;

    /* The single-byte matcher means we can't proceed in UTF-8 mode. (In
    non-UTF-8 mode \C will actually be turned into OP_ALLANY, so won't ever
    appear, but leave the code, just in case.) */

    case OP_ANYBYTE:
#ifdef SUPPORT_UTF
    if (utf) return -1;
#endif
    branchlength++;
    cc++;
    break;

    /* For repeated character types, we have to test for \p and \P, which have
    an extra two bytes of parameters. */

    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    case OP_TYPEPOSSTAR:
    case OP_TYPEPOSQUERY:
    if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2;
    cc += PRIV(OP_lengths)[op];
    break;

    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    case OP_TYPEPOSUPTO:
    if (cc[1 + IMM2_SIZE] == OP_PROP
      || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2;
    cc += PRIV(OP_lengths)[op];
    break;

    /* Check a class for variable quantification */

#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
    case OP_XCLASS:
    cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
    /* Fall through */
#endif

    case OP_CLASS:
    case OP_NCLASS:
    cc += PRIV(OP_lengths)[OP_CLASS];

    switch (*cc)
      {
      case OP_CRPLUS:
      case OP_CRMINPLUS:
      branchlength++;
      /* Fall through */

      case OP_CRSTAR:
      case OP_CRMINSTAR:
      case OP_CRQUERY:
      case OP_CRMINQUERY:
      cc++;
      break;

      case OP_CRRANGE:
      case OP_CRMINRANGE:
      branchlength += GET2(cc,1);
      cc += 1 + 2 * IMM2_SIZE;
      break;

      default:
      branchlength++;
      break;
      }
    break;

    /* Backreferences and subroutine calls are treated in the same way: we find
    the minimum length for the subpattern. A recursion, however, causes an
    a flag to be set that causes the length of this branch to be ignored. The
    logic is that a recursion can only make sense if there is another
    alternation that stops the recursing. That will provide the minimum length
    (when no recursion happens). A backreference within the group that it is
    referencing behaves in the same way.

    If PCRE_JAVASCRIPT_COMPAT is set, a backreference to an unset bracket
    matches an empty string (by default it causes a matching failure), so in
    that case we must set the minimum length to zero. */

    case OP_REF:
    case OP_REFI:
    if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
      {
      ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1));
      if (cs == NULL) return -2;
      do ce += GET(ce, 1); while (*ce == OP_ALT);
      if (cc > cs && cc < ce)
        {
        d = 0;
        had_recurse = TRUE;
        }
      else
        {
        d = find_minlength(cs, startcode, options, recurse_depth);
        }
      }
    else d = 0;
    cc += 1 + IMM2_SIZE;

    /* Handle repeated back references */

    switch (*cc)
      {
      case OP_CRSTAR:
      case OP_CRMINSTAR:
      case OP_CRQUERY:
      case OP_CRMINQUERY:
      min = 0;
      cc++;
      break;

      case OP_CRPLUS:
      case OP_CRMINPLUS:
      min = 1;
      cc++;
      break;

      case OP_CRRANGE:
      case OP_CRMINRANGE:
      min = GET2(cc, 1);
      cc += 1 + 2 * IMM2_SIZE;
      break;

      default:
      min = 1;
      break;
      }

    branchlength += min * d;
    break;

    /* We can easily detect direct recursion, but not mutual recursion. This is
    caught by a recursion depth count. */

    case OP_RECURSE:
    cs = ce = (pcre_uchar *)startcode + GET(cc, 1);
    do ce += GET(ce, 1); while (*ce == OP_ALT);
    if ((cc > cs && cc < ce) || recurse_depth > 10)
      had_recurse = TRUE;
    else
      {
      branchlength += find_minlength(cs, startcode, options, recurse_depth + 1);
      }
    cc += 1 + LINK_SIZE;
    break;

    /* Anything else does not or need not match a character. We can get the
    item's length from the table, but for those that can match zero occurrences
    of a character, we must take special action for UTF-8 characters. As it
    happens, the "NOT" versions of these opcodes are used at present only for
    ASCII characters, so they could be omitted from this list. However, in
    future that may change, so we include them here so as not to leave a
    gotcha for a future maintainer. */

    case OP_UPTO:
    case OP_UPTOI:
    case OP_NOTUPTO:
    case OP_NOTUPTOI:
    case OP_MINUPTO:
    case OP_MINUPTOI:
    case OP_NOTMINUPTO:
    case OP_NOTMINUPTOI:
    case OP_POSUPTO:
    case OP_POSUPTOI:
    case OP_NOTPOSUPTO:
    case OP_NOTPOSUPTOI:

    case OP_STAR:
    case OP_STARI:
    case OP_NOTSTAR:
    case OP_NOTSTARI:
    case OP_MINSTAR:
    case OP_MINSTARI:
    case OP_NOTMINSTAR:
    case OP_NOTMINSTARI:
    case OP_POSSTAR:
    case OP_POSSTARI:
    case OP_NOTPOSSTAR:
    case OP_NOTPOSSTARI:

    case OP_QUERY:
    case OP_QUERYI:
    case OP_NOTQUERY:
    case OP_NOTQUERYI:
    case OP_MINQUERY:
    case OP_MINQUERYI:
    case OP_NOTMINQUERY:
    case OP_NOTMINQUERYI:
    case OP_POSQUERY:
    case OP_POSQUERYI:
    case OP_NOTPOSQUERY:
    case OP_NOTPOSQUERYI:

    cc += PRIV(OP_lengths)[op];
#ifdef SUPPORT_UTF
    if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
    break;

    /* Skip these, but we need to add in the name length. */

    case OP_MARK:
    case OP_PRUNE_ARG:
    case OP_SKIP_ARG:
    case OP_THEN_ARG:
    cc += PRIV(OP_lengths)[op] + cc[1];
    break;

    /* The remaining opcodes are just skipped over. */

    case OP_CLOSE:
    case OP_COMMIT:
    case OP_FAIL:
    case OP_PRUNE:
    case OP_SET_SOM:
    case OP_SKIP:
    case OP_THEN:
    cc += PRIV(OP_lengths)[op];
    break;

    /* This should not occur: we list all opcodes explicitly so that when
    new ones get added they are properly considered. */

    default:
    return -3;
    }
  }
/* Control never gets here */
}



/*************************************************
*      Set a bit and maybe its alternate case    *
*************************************************/

/* Given a character, set its first byte's bit in the table, and also the
corresponding bit for the other version of a letter if we are caseless. In
UTF-8 mode, for characters greater than 127, we can only do the caseless thing
when Unicode property support is available.

Arguments:
  start_bits    points to the bit map
  p             points to the character
  caseless      the caseless flag
  cd            the block with char table pointers
  utf           TRUE for UTF-8 / UTF-16 mode

Returns:        pointer after the character
*/

static const pcre_uchar *
set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless,
  compile_data *cd, BOOL utf)
{
unsigned int c = *p;

#ifdef COMPILE_PCRE8
SET_BIT(c);

#ifdef SUPPORT_UTF
if (utf && c > 127)
  {
  GETCHARINC(c, p);
#ifdef SUPPORT_UCP
  if (caseless)
    {
    pcre_uchar buff[6];
    c = UCD_OTHERCASE(c);
    (void)PRIV(ord2utf)(c, buff);
    SET_BIT(buff[0]);
    }
#endif
  return p;
  }
#endif

/* Not UTF-8 mode, or character is less than 127. */

if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
return p + 1;
#endif

#ifdef COMPILE_PCRE16
if (c > 0xff)
  {
  c = 0xff;
  caseless = FALSE;
  }
SET_BIT(c);

#ifdef SUPPORT_UTF
if (utf && c > 127)
  {
  GETCHARINC(c, p);
#ifdef SUPPORT_UCP
  if (caseless)
    {
    c = UCD_OTHERCASE(c);
    if (c > 0xff)
      c = 0xff;
    SET_BIT(c);
    }
#endif
  return p;
  }
#endif

if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
return p + 1;
#endif
}



/*************************************************
*     Set bits for a positive character type     *
*************************************************/

/* This function sets starting bits for a character type. In UTF-8 mode, we can
only do a direct setting for bytes less than 128, as otherwise there can be
confusion with bytes in the middle of UTF-8 characters. In a "traditional"
environment, the tables will only recognize ASCII characters anyway, but in at
least one Windows environment, some higher bytes bits were set in the tables.
So we deal with that case by considering the UTF-8 encoding.

Arguments:
  start_bits     the starting bitmap
  cbit type      the type of character wanted
  table_limit    32 for non-UTF-8; 16 for UTF-8
  cd             the block with char table pointers

Returns:         nothing
*/

static void
set_type_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
  compile_data *cd)
{
register int c;
for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type];
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (table_limit == 32) return;
for (c = 128; c < 256; c++)
  {
  if ((cd->cbits[c/8] & (1 << (c&7))) != 0)
    {
    pcre_uchar buff[6];
    (void)PRIV(ord2utf)(c, buff);
    SET_BIT(buff[0]);
    }
  }
#endif
}


/*************************************************
*     Set bits for a negative character type     *
*************************************************/

/* This function sets starting bits for a negative character type such as \D.
In UTF-8 mode, we can only do a direct setting for bytes less than 128, as
otherwise there can be confusion with bytes in the middle of UTF-8 characters.
Unlike in the positive case, where we can set appropriate starting bits for
specific high-valued UTF-8 characters, in this case we have to set the bits for
all high-valued characters. The lowest is 0xc2, but we overkill by starting at
0xc0 (192) for simplicity.

Arguments:
  start_bits     the starting bitmap
  cbit type      the type of character wanted
  table_limit    32 for non-UTF-8; 16 for UTF-8
  cd             the block with char table pointers

Returns:         nothing
*/

static void
set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
  compile_data *cd)
{
register int c;
for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type];
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff;
#endif
}



/*************************************************
*          Create bitmap of starting bytes       *
*************************************************/

/* This function scans a compiled unanchored expression recursively and
attempts to build a bitmap of the set of possible starting bytes. As time goes
by, we may be able to get more clever at doing this. The SSB_CONTINUE return is
useful for parenthesized groups in patterns such as (a*)b where the group
provides some optional starting bytes but scanning must continue at the outer
level to find at least one mandatory byte. At the outermost level, this
function fails unless the result is SSB_DONE.

Arguments:
  code         points to an expression
  start_bits   points to a 32-byte table, initialized to 0
  utf          TRUE if in UTF-8 / UTF-16 mode
  cd           the block with char table pointers

Returns:       SSB_FAIL     => Failed to find any starting bytes
               SSB_DONE     => Found mandatory starting bytes
               SSB_CONTINUE => Found optional starting bytes
               SSB_UNKNOWN  => Hit an unrecognized opcode
*/

static int
set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf,
  compile_data *cd)
{
register int c;
int yield = SSB_DONE;
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
int table_limit = utf? 16:32;
#else
int table_limit = 32;
#endif

#if 0
/* ========================================================================= */
/* The following comment and code was inserted in January 1999. In May 2006,
when it was observed to cause compiler warnings about unused values, I took it
out again. If anybody is still using OS/2, they will have to put it back
manually. */

/* This next statement and the later reference to dummy are here in order to
trick the optimizer of the IBM C compiler for OS/2 into generating correct
code. Apparently IBM isn't going to fix the problem, and we would rather not
disable optimization (in this module it actually makes a big difference, and
the pcre module can use all the optimization it can get). */

volatile int dummy;
/* ========================================================================= */
#endif

do
  {
  BOOL try_next = TRUE;
  const pcre_uchar *tcode = code + 1 + LINK_SIZE;

  if (*code == OP_CBRA || *code == OP_SCBRA ||
      *code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE;

  while (try_next)    /* Loop for items in this branch */
    {
    int rc;

    switch(*tcode)
      {
      /* If we reach something we don't understand, it means a new opcode has
      been created that hasn't been added to this code. Hopefully this problem
      will be discovered during testing. */

      default:
      return SSB_UNKNOWN;

      /* Fail for a valid opcode that implies no starting bits. */

      case OP_ACCEPT:
      case OP_ASSERT_ACCEPT:
      case OP_ALLANY:
      case OP_ANY:
      case OP_ANYBYTE:
      case OP_CIRC:
      case OP_CIRCM:
      case OP_CLOSE:
      case OP_COMMIT:
      case OP_COND:
      case OP_CREF:
      case OP_DEF:
      case OP_DOLL:
      case OP_DOLLM:
      case OP_END:
      case OP_EOD:
      case OP_EODN:
      case OP_EXTUNI:
      case OP_FAIL:
      case OP_MARK:
      case OP_NCREF:
      case OP_NOT:
      case OP_NOTEXACT:
      case OP_NOTEXACTI:
      case OP_NOTI:
      case OP_NOTMINPLUS:
      case OP_NOTMINPLUSI:
      case OP_NOTMINQUERY:
      case OP_NOTMINQUERYI:
      case OP_NOTMINSTAR:
      case OP_NOTMINSTARI:
      case OP_NOTMINUPTO:
      case OP_NOTMINUPTOI:
      case OP_NOTPLUS:
      case OP_NOTPLUSI:
      case OP_NOTPOSPLUS:
      case OP_NOTPOSPLUSI:
      case OP_NOTPOSQUERY:
      case OP_NOTPOSQUERYI:
      case OP_NOTPOSSTAR:
      case OP_NOTPOSSTARI:
      case OP_NOTPOSUPTO:
      case OP_NOTPOSUPTOI:
      case OP_NOTPROP:
      case OP_NOTQUERY:
      case OP_NOTQUERYI:
      case OP_NOTSTAR:
      case OP_NOTSTARI:
      case OP_NOTUPTO:
      case OP_NOTUPTOI:
      case OP_NOT_HSPACE:
      case OP_NOT_VSPACE:
      case OP_NRREF:
      case OP_PROP:
      case OP_PRUNE:
      case OP_PRUNE_ARG:
      case OP_RECURSE:
      case OP_REF:
      case OP_REFI:
      case OP_REVERSE:
      case OP_RREF:
      case OP_SCOND:
      case OP_SET_SOM:
      case OP_SKIP:
      case OP_SKIP_ARG:
      case OP_SOD:
      case OP_SOM:
      case OP_THEN:
      case OP_THEN_ARG:
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
      case OP_XCLASS:
#endif
      return SSB_FAIL;

      /* We can ignore word boundary tests. */

      case OP_WORD_BOUNDARY:
      case OP_NOT_WORD_BOUNDARY:
      tcode++;
      break;

      /* If we hit a bracket or a positive lookahead assertion, recurse to set
      bits from within the subpattern. If it can't find anything, we have to
      give up. If it finds some mandatory character(s), we are done for this
      branch. Otherwise, carry on scanning after the subpattern. */

      case OP_BRA:
      case OP_SBRA:
      case OP_CBRA:
      case OP_SCBRA:
      case OP_BRAPOS:
      case OP_SBRAPOS:
      case OP_CBRAPOS:
      case OP_SCBRAPOS:
      case OP_ONCE:
      case OP_ONCE_NC:
      case OP_ASSERT:
      rc = set_start_bits(tcode, start_bits, utf, cd);
      if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
      if (rc == SSB_DONE) try_next = FALSE; else
        {
        do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
        tcode += 1 + LINK_SIZE;
        }
      break;

      /* If we hit ALT or KET, it means we haven't found anything mandatory in
      this branch, though we might have found something optional. For ALT, we
      continue with the next alternative, but we have to arrange that the final
      result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET,
      return SSB_CONTINUE: if this is the top level, that indicates failure,
      but after a nested subpattern, it causes scanning to continue. */

      case OP_ALT:
      yield = SSB_CONTINUE;
      try_next = FALSE;
      break;

      case OP_KET:
      case OP_KETRMAX:
      case OP_KETRMIN:
      case OP_KETRPOS:
      return SSB_CONTINUE;

      /* Skip over callout */

      case OP_CALLOUT:
      tcode += 2 + 2*LINK_SIZE;
      break;

      /* Skip over lookbehind and negative lookahead assertions */

      case OP_ASSERT_NOT:
      case OP_ASSERTBACK:
      case OP_ASSERTBACK_NOT:
      do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
      tcode += 1 + LINK_SIZE;
      break;

      /* BRAZERO does the bracket, but carries on. */

      case OP_BRAZERO:
      case OP_BRAMINZERO:
      case OP_BRAPOSZERO:
      rc = set_start_bits(++tcode, start_bits, utf, cd);
      if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
/* =========================================================================
      See the comment at the head of this function concerning the next line,
      which was an old fudge for the benefit of OS/2.
      dummy = 1;
  ========================================================================= */
      do tcode += GET(tcode,1); while (*tcode == OP_ALT);
      tcode += 1 + LINK_SIZE;
      break;

      /* SKIPZERO skips the bracket. */

      case OP_SKIPZERO:
      tcode++;
      do tcode += GET(tcode,1); while (*tcode == OP_ALT);
      tcode += 1 + LINK_SIZE;
      break;

      /* Single-char * or ? sets the bit and tries the next item */

      case OP_STAR:
      case OP_MINSTAR:
      case OP_POSSTAR:
      case OP_QUERY:
      case OP_MINQUERY:
      case OP_POSQUERY:
      tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
      break;

      case OP_STARI:
      case OP_MINSTARI:
      case OP_POSSTARI:
      case OP_QUERYI:
      case OP_MINQUERYI:
      case OP_POSQUERYI:
      tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
      break;

      /* Single-char upto sets the bit and tries the next */

      case OP_UPTO:
      case OP_MINUPTO:
      case OP_POSUPTO:
      tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf);
      break;

      case OP_UPTOI:
      case OP_MINUPTOI:
      case OP_POSUPTOI:
      tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf);
      break;

      /* At least one single char sets the bit and stops */

      case OP_EXACT:
      tcode += IMM2_SIZE;
      /* Fall through */
      case OP_CHAR:
      case OP_PLUS:
      case OP_MINPLUS:
      case OP_POSPLUS:
      (void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
      try_next = FALSE;
      break;

      case OP_EXACTI:
      tcode += IMM2_SIZE;
      /* Fall through */
      case OP_CHARI:
      case OP_PLUSI:
      case OP_MINPLUSI:
      case OP_POSPLUSI:
      (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
      try_next = FALSE;
      break;

      /* Special spacing and line-terminating items. These recognize specific
      lists of characters. The difference between VSPACE and ANYNL is that the
      latter can match the two-character CRLF sequence, but that is not
      relevant for finding the first character, so their code here is
      identical. */

      case OP_HSPACE:
      SET_BIT(0x09);
      SET_BIT(0x20);
#ifdef SUPPORT_UTF
      if (utf)
        {
#ifdef COMPILE_PCRE8
        SET_BIT(0xC2);  /* For U+00A0 */
        SET_BIT(0xE1);  /* For U+1680, U+180E */
        SET_BIT(0xE2);  /* For U+2000 - U+200A, U+202F, U+205F */
        SET_BIT(0xE3);  /* For U+3000 */
#endif
#ifdef COMPILE_PCRE16
        SET_BIT(0xA0);
        SET_BIT(0xFF);  /* For characters > 255 */
#endif
        }
      else
#endif /* SUPPORT_UTF */
        {
        SET_BIT(0xA0);
#ifdef COMPILE_PCRE16
        SET_BIT(0xFF);  /* For characters > 255 */
#endif
        }
      try_next = FALSE;
      break;

      case OP_ANYNL:
      case OP_VSPACE:
      SET_BIT(0x0A);
      SET_BIT(0x0B);
      SET_BIT(0x0C);
      SET_BIT(0x0D);
#ifdef SUPPORT_UTF
      if (utf)
        {
#ifdef COMPILE_PCRE8
        SET_BIT(0xC2);  /* For U+0085 */
        SET_BIT(0xE2);  /* For U+2028, U+2029 */
#endif
#ifdef COMPILE_PCRE16
        SET_BIT(0x85);
        SET_BIT(0xFF);  /* For characters > 255 */
#endif
        }
      else
#endif /* SUPPORT_UTF */
        {
        SET_BIT(0x85);
#ifdef COMPILE_PCRE16
        SET_BIT(0xFF);  /* For characters > 255 */
#endif
        }
      try_next = FALSE;
      break;

      /* Single character types set the bits and stop. Note that if PCRE_UCP
      is set, we do not see these op codes because \d etc are converted to
      properties. Therefore, these apply in the case when only characters less
      than 256 are recognized to match the types. */

      case OP_NOT_DIGIT:
      set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
      try_next = FALSE;
      break;

      case OP_DIGIT:
      set_type_bits(start_bits, cbit_digit, table_limit, cd);
      try_next = FALSE;
      break;

      /* The cbit_space table has vertical tab as whitespace; we have to
      ensure it is set as not whitespace. */

      case OP_NOT_WHITESPACE:
      set_nottype_bits(start_bits, cbit_space, table_limit, cd);
      start_bits[1] |= 0x08;
      try_next = FALSE;
      break;

      /* The cbit_space table has vertical tab as whitespace; we have to
      not set it from the table. */

      case OP_WHITESPACE:
      c = start_bits[1];    /* Save in case it was already set */
      set_type_bits(start_bits, cbit_space, table_limit, cd);
      start_bits[1] = (start_bits[1] & ~0x08) | c;
      try_next = FALSE;
      break;

      case OP_NOT_WORDCHAR:
      set_nottype_bits(start_bits, cbit_word, table_limit, cd);
      try_next = FALSE;
      break;

      case OP_WORDCHAR:
      set_type_bits(start_bits, cbit_word, table_limit, cd);
      try_next = FALSE;
      break;

      /* One or more character type fudges the pointer and restarts, knowing
      it will hit a single character type and stop there. */

      case OP_TYPEPLUS:
      case OP_TYPEMINPLUS:
      case OP_TYPEPOSPLUS:
      tcode++;
      break;

      case OP_TYPEEXACT:
      tcode += 1 + IMM2_SIZE;
      break;

      /* Zero or more repeats of character types set the bits and then
      try again. */

      case OP_TYPEUPTO:
      case OP_TYPEMINUPTO:
      case OP_TYPEPOSUPTO:
      tcode += IMM2_SIZE;  /* Fall through */

      case OP_TYPESTAR:
      case OP_TYPEMINSTAR:
      case OP_TYPEPOSSTAR:
      case OP_TYPEQUERY:
      case OP_TYPEMINQUERY:
      case OP_TYPEPOSQUERY:
      switch(tcode[1])
        {
        default:
        case OP_ANY:
        case OP_ALLANY:
        return SSB_FAIL;

        case OP_HSPACE:
        SET_BIT(0x09);
        SET_BIT(0x20);
#ifdef SUPPORT_UTF
        if (utf)
          {
#ifdef COMPILE_PCRE8
          SET_BIT(0xC2);  /* For U+00A0 */
          SET_BIT(0xE1);  /* For U+1680, U+180E */
          SET_BIT(0xE2);  /* For U+2000 - U+200A, U+202F, U+205F */
          SET_BIT(0xE3);  /* For U+3000 */
#endif
#ifdef COMPILE_PCRE16
          SET_BIT(0xA0);
          SET_BIT(0xFF);  /* For characters > 255 */
#endif
          }
        else
#endif /* SUPPORT_UTF */
          SET_BIT(0xA0);
        break;

        case OP_ANYNL:
        case OP_VSPACE:
        SET_BIT(0x0A);
        SET_BIT(0x0B);
        SET_BIT(0x0C);
        SET_BIT(0x0D);
#ifdef SUPPORT_UTF
        if (utf)
          {
#ifdef COMPILE_PCRE8
          SET_BIT(0xC2);  /* For U+0085 */
          SET_BIT(0xE2);  /* For U+2028, U+2029 */
#endif
#ifdef COMPILE_PCRE16
          SET_BIT(0x85);
          SET_BIT(0xFF);  /* For characters > 255 */
#endif
          }
        else
#endif /* SUPPORT_UTF */
          SET_BIT(0x85);
        break;

        case OP_NOT_DIGIT:
        set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
        break;

        case OP_DIGIT:
        set_type_bits(start_bits, cbit_digit, table_limit, cd);
        break;

        /* The cbit_space table has vertical tab as whitespace; we have to
        ensure it gets set as not whitespace. */

        case OP_NOT_WHITESPACE:
        set_nottype_bits(start_bits, cbit_space, table_limit, cd);
        start_bits[1] |= 0x08;
        break;

        /* The cbit_space table has vertical tab as whitespace; we have to
        avoid setting it. */

        case OP_WHITESPACE:
        c = start_bits[1];    /* Save in case it was already set */
        set_type_bits(start_bits, cbit_space, table_limit, cd);
        start_bits[1] = (start_bits[1] & ~0x08) | c;
        break;

        case OP_NOT_WORDCHAR:
        set_nottype_bits(start_bits, cbit_word, table_limit, cd);
        break;

        case OP_WORDCHAR:
        set_type_bits(start_bits, cbit_word, table_limit, cd);
        break;
        }

      tcode += 2;
      break;

      /* Character class where all the information is in a bit map: set the
      bits and either carry on or not, according to the repeat count. If it was
      a negative class, and we are operating with UTF-8 characters, any byte
      with a value >= 0xc4 is a potentially valid starter because it starts a
      character with a value > 255. */

      case OP_NCLASS:
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
      if (utf)
        {
        start_bits[24] |= 0xf0;              /* Bits for 0xc4 - 0xc8 */
        memset(start_bits+25, 0xff, 7);      /* Bits for 0xc9 - 0xff */
        }
#endif
#ifdef COMPILE_PCRE16
      SET_BIT(0xFF);                         /* For characters > 255 */
#endif
      /* Fall through */

      case OP_CLASS:
        {
        pcre_uint8 *map;
        tcode++;
        map = (pcre_uint8 *)tcode;

        /* In UTF-8 mode, the bits in a bit map correspond to character
        values, not to byte values. However, the bit map we are constructing is
        for byte values. So we have to do a conversion for characters whose
        value is > 127. In fact, there are only two possible starting bytes for
        characters in the range 128 - 255. */

#if defined SUPPORT_UTF && defined COMPILE_PCRE8
        if (utf)
          {
          for (c = 0; c < 16; c++) start_bits[c] |= map[c];
          for (c = 128; c < 256; c++)
            {
            if ((map[c/8] && (1 << (c&7))) != 0)
              {
              int d = (c >> 6) | 0xc0;            /* Set bit for this starter */
              start_bits[d/8] |= (1 << (d&7));    /* and then skip on to the */
              c = (c & 0xc0) + 0x40 - 1;          /* next relevant character. */
              }
            }
          }
        else
#endif
          {
          /* In non-UTF-8 mode, the two bit maps are completely compatible. */
          for (c = 0; c < 32; c++) start_bits[c] |= map[c];
          }

        /* Advance past the bit map, and act on what follows. For a zero
        minimum repeat, continue; otherwise stop processing. */

        tcode += 32 / sizeof(pcre_uchar);
        switch (*tcode)
          {
          case OP_CRSTAR:
          case OP_CRMINSTAR:
          case OP_CRQUERY:
          case OP_CRMINQUERY:
          tcode++;
          break;

          case OP_CRRANGE:
          case OP_CRMINRANGE:
          if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;
            else try_next = FALSE;
          break;

          default:
          try_next = FALSE;
          break;
          }
        }
      break; /* End of bitmap class handling */

      }      /* End of switch */
    }        /* End of try_next loop */

  code += GET(code, 1);   /* Advance to next branch */
  }
while (*code == OP_ALT);
return yield;
}





/*************************************************
*          Study a compiled expression           *
*************************************************/

/* This function is handed a compiled expression that it must study to produce
information that will speed up the matching. It returns a pcre[16]_extra block
which then gets handed back to PCREXEC8().

Arguments:
  re        points to the compiled expression
  options   contains option bits
  errorptr  points to where to place error messages;
            set NULL unless error

Returns:    pointer to a pcre[16]_extra block, with study_data filled in and
              the appropriate flags set;
            NULL on error or if no optimization possible
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
STUDY8(const pcre *external_re, int options, const char **errorptr)
#else
PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
pcre16_study(const pcre16 *external_re, int options, const char **errorptr)
#endif
{
int min;
BOOL bits_set = FALSE;
pcre_uint8 start_bits[32];
PUBL(extra) *extra = NULL;
pcre_study_data *study;
const pcre_uint8 *tables;
pcre_uchar *code;
compile_data compile_block;
const REAL_PCRE *re = (const REAL_PCRE *)external_re;

*errorptr = NULL;

if (re == NULL || re->magic_number != MAGIC_NUMBER)
  {
  *errorptr = "argument is not a compiled regular expression";
  return NULL;
  }

if ((re->flags & PCRE_MODE) == 0)
  {
#ifdef COMPILE_PCRE8
  *errorptr = "argument is compiled in 16 bit mode";
#else
  *errorptr = "argument is compiled in 8 bit mode";
#endif
  return NULL;
  }

if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
  {
  *errorptr = "unknown or incorrect option bit(s) set";
  return NULL;
  }

code = (pcre_uchar *)re + re->name_table_offset +
  (re->name_count * re->name_entry_size);

/* For an anchored pattern, or an unanchored pattern that has a first char, or
a multiline pattern that matches only at "line starts", there is no point in
seeking a list of starting bytes. */

if ((re->options & PCRE_ANCHORED) == 0 &&
    (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) == 0)
  {
  int rc;

  /* Set the character tables in the block that is passed around */

  tables = re->tables;

#ifdef COMPILE_PCRE8
  if (tables == NULL)
    (void)FULLINF8(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
    (void *)(&tables));
#else
  if (tables == NULL)
    (void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
    (void *)(&tables));
#endif

  compile_block.lcc = tables + lcc_offset;
  compile_block.fcc = tables + fcc_offset;
  compile_block.cbits = tables + cbits_offset;
  compile_block.ctypes = tables + ctypes_offset;

  /* See if we can find a fixed set of initial characters for the pattern. */

  memset(start_bits, 0, 32 * sizeof(pcre_uint8));
  rc = set_start_bits(code, start_bits, (re->options & PCRE_UTF8) != 0,
    &compile_block);
  bits_set = rc == SSB_DONE;
  if (rc == SSB_UNKNOWN)
    {
    *errorptr = "internal error: opcode not recognized";
    return NULL;
    }
  }

/* Find the minimum length of subject string. */

switch(min = find_minlength(code, code, re->options, 0))
  {
  case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
  case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
  default: break;
  }

/* If a set of starting bytes has been identified, or if the minimum length is
greater than zero, or if JIT optimization has been requested, get a
pcre[16]_extra block and a pcre_study_data block. The study data is put in the
latter, which is pointed to by the former, which may also get additional data
set later by the calling program. At the moment, the size of pcre_study_data
is fixed. We nevertheless save it in a field for returning via the
FULLINF8() function so that if it becomes variable in the future,
we don't have to change that code. */

if (bits_set || min > 0
#ifdef SUPPORT_JIT
    || (options & (PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
                 | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE)) != 0
#endif
  )
  {
  extra = (PUBL(extra) *)(PUBL(malloc))
    (sizeof(PUBL(extra)) + sizeof(pcre_study_data));
  if (extra == NULL)
    {
    *errorptr = "failed to get memory";
    return NULL;
    }

  study = (pcre_study_data *)((char *)extra + sizeof(PUBL(extra)));
  extra->flags = PCRE_EXTRA_STUDY_DATA;
  extra->study_data = study;

  study->size = sizeof(pcre_study_data);
  study->flags = 0;

  /* Set the start bits always, to avoid unset memory errors if the
  study data is written to a file, but set the flag only if any of the bits
  are set, to save time looking when none are. */

  if (bits_set)
    {
    study->flags |= PCRE_STUDY_MAPPED;
    memcpy(study->start_bits, start_bits, sizeof(start_bits));
    }
  else memset(study->start_bits, 0, 32 * sizeof(pcre_uint8));

#ifdef PCRE_DEBUG
  if (bits_set)
    {
    pcre_uint8 *ptr = start_bits;
    int i;

    printf("Start bits:\n");
    for (i = 0; i < 32; i++)
      printf("%3d: %02x%s", i * 8, *ptr++, ((i + 1) & 0x7) != 0? " " : "\n");
    }
#endif

  /* Always set the minlength value in the block, because the JIT compiler
  makes use of it. However, don't set the bit unless the length is greater than
  zero - the interpretive PCREXEC8() and DFAEXEC8() needn't waste time
  checking the zero case. */

  if (min > 0)
    {
    study->flags |= PCRE_STUDY_MINLEN;
    study->minlength = min;
    }
  else study->minlength = 0;

  /* If JIT support was compiled and requested, attempt the JIT compilation.
  If no starting bytes were found, and the minimum length is zero, and JIT
  compilation fails, abandon the extra block and return NULL. */

#ifdef SUPPORT_JIT
  extra->executable_jit = NULL;
  if ((options & PCRE_STUDY_JIT_COMPILE) != 0)
    PRIV(jit_compile)(re, extra, JIT_COMPILE);
  if ((options & PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE) != 0)
    PRIV(jit_compile)(re, extra, JIT_PARTIAL_SOFT_COMPILE);
  if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0)
    PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE);

  if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0)
    {
#ifdef COMPILE_PCRE8
    pcre_free_study(extra);
#endif
#ifdef COMPILE_PCRE16
    pcre16_free_study(extra);
#endif
    extra = NULL;
    }
#endif
  }

return extra;
}


/*************************************************
*          Free the study data                   *
*************************************************/

/* This function frees the memory that was obtained by STUDY8().

Argument:   a pointer to the pcre[16]_extra block
Returns:    nothing
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN void
pcre_free_study(pcre_extra *extra)
#else
PCRE_EXP_DEFN void
pcre16_free_study(pcre16_extra *extra)
#endif
{
if (extra == NULL)
  return;
#ifdef SUPPORT_JIT
if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
     extra->executable_jit != NULL)
  PRIV(jit_free)(extra->executable_jit);
#endif
PUBL(free)(extra);
}

/* End of STUDY8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_study.c converted to STUDY8*/
/*autoconv-0013 STUDY8 line: 41 pcre_study replaced by STUDY8*/
/*autoconv-0010 STUDY8 line: 46 added HAVE_CONFIG_H*/
/*autoconv-0011 STUDY8 line: 49 config.h replaced by CONFIG.h*/
/*autoconv-0011 STUDY8 line: 52 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 STUDY8 line: 1305 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 STUDY8 line: 1320 pcre_study replaced by STUDY8*/
/*autoconv-0013 STUDY8 line: 1378 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 STUDY8 line: 1419 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 STUDY8 line: 1469 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 STUDY8 line: 1469 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 STUDY8 line: 1513 pcre_study replaced by STUDY8*/
/*autoconv-0013 STUDY8 line: 1537 pcre_study replaced by STUDY8*/
./ ADD NAME=PCOBAPI 
/*
THE z/OS specific functionality
-------------------------------

Contributed by:   Ze'ev Atlas.

Copyright (c) 2012, Ze'ev Atlas.
All rights reserved.


THE "BSD" LICENCE
-----------------

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the name of Google
      Inc. nor the names of their contributors may be used to endorse or
      promote products derived from this software without specific prior
      written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.                                          */
/****************************************************************************
* The PCOBAPI provides old style z/OS COBOL with the ability to call        *
* traditional z/OS short (8 characters) names.  In this first version I     *
* converted the API man page to simple C program and created short names    *
* manually.  I will reintroduce an algorithmic way to do it into the        *
* conversion scripts once I get back to them, though names that are already *
* decided upon will stay as is.  Also, subsequent conversion scripts might  *
* generate this program automatically from my database.      ZA 10/28/2012  *
****************************************************************************/
/*PCREAPI(3)
NAME  PCRE - Perl-compatible regular expressions */

/*PCRE 16-BIT API ... pcre16_... and the anticipated pcre32_...
       = all pcre16_ and the anticipated pcre32_ are specifically not
         supported.  The z/OS port is meant to support native EBCDIC
         environment only!	*/	

#include <stdlib.h>
#include "pcre.h"
#include "posixh.h"
extern  pcre * COMPILE2(const char *pattern, int options,
            int *errorcodeptr,
            const char **errptr, int *erroffset,
            const unsigned char *tableptr);

extern void FRESTUDY(pcre_extra *extra);

extern int CPYNMSBS(const pcre *code,
            const char *subject, int *ovector,
            int stringcount, const char *stringname,
            char *buffer, int buffersize);

extern int CPYSBSTR(const char *subject, int *ovector,
            int stringcount, int stringnumber, char *buffer,
            int buffersize);

extern int GETNMSBS(const pcre *code,
            const char *subject, int *ovector,
            int stringcount, const char *stringname,
            const char **stringptr);

extern int GETSTNMB(const pcre *code,
            const char *name);

extern int GETSTTBE(const pcre *code,
            const char *name, char **first, char **last);

extern int GETSBSTR(const char *subject, int *ovector,
            int stringcount, int stringnumber,
            const char **stringptr);

extern int GETSBSLS(const char *subject,
            int *ovector, int stringcount, const char ***listptr);

extern void FRESBSTR(const char *stringptr);

extern void FRESBSLS(const char **stringptr);

extern pcre_jit_stack *ALCJITST(int startsize, int maxsize);

extern void FREJITST(pcre_jit_stack *stack);

extern void ASGJITST(pcre_extra *extra,
            pcre_jit_callback callback, void *data);

extern int PT2HBTOR(pcre *code,
            pcre_extra *extra, const unsigned char *tables);

/*extern void *(*PMALLOC)(size_t);

extern void (*PFREE)(void *);

extern void *(*PSMALLOC)(size_t);

extern void (*PSFREE)(void *);

extern int (*PCALLOUT)(pcre_callout_block *);*/

extern int PREGCOMP(regex_t *preg, const char *pattern,
            int cflags);

extern int PREGEXEC(regex_t *preg, const char *string,
            size_t nmatch, regmatch_t pmatch[], int eflags);

extern size_t PREGERR(int errcode, const regex_t *preg,
            char *errbuf, size_t errbuf_size);

extern void PREGFREE(regex_t *preg);

extern int ZWHTTRM (char * str, int maxlen);
	
extern int ZISSPTRM (char * str, int maxlen);
	
extern int ZISNLTRM (char * str, int maxlen);
	
extern int ZSPC2NUL (char * str, int maxlen);
	
extern int ZNUL2SPC (char * str, int maxlen);			
			
/*PCRE NATIVE API BASIC FUNCTIONS */

/*       => COMPILE8
	   pcre *pcre_compile(const char *pattern, int options,
            const char **errptr, int *erroffset,
            const unsigned char *tableptr);*/

/*	   = part of COMPILE8 - supported as is via PGMNAME(LONGMIXED) */
pcre *COMPILE2(const char *pattern, int options,
            int *errorcodeptr,
            const char **errptr, int *erroffset,
            const unsigned char *tableptr)
{
        return pcre_compile2(pattern, options,
            errorcodeptr,
            errptr, erroffset,
            tableptr);
}

/*       => STUDY8
	   pcre_extra *pcre_study(const pcre *code, int options,
            const char **errptr);*/

/*	   = part of STUDY8 - supported as is via PGMNAME(LONGMIXED)	*/
void FRESTUDY(pcre_extra *extra)
{		
              pcre_free_study(extra);
}

/*       => EXEC8
	   int pcre_exec(const pcre *code, const pcre_extra *extra,
            const char *subject, int length, int startoffset,
            int options, int *ovector, int ovecsize);*/

/*       => DFAEXEC8
	   int pcre_dfa_exec(const pcre *code, const pcre_extra *extra,
            const char *subject, int length, int startoffset,
            int options, int *ovector, int ovecsize,
            int *workspace, int wscount);*/

/*PCRE NATIVE API STRING EXTRACTION FUNCTIONS*/

/*	   = all are part of GET8 - supported as is via PGMNAME(LONGMIXED)*/
int CPYNMSBS(const pcre *code,
            const char *subject, int *ovector,
            int stringcount, const char *stringname,
            char *buffer, int buffersize)
{
		return pcre_copy_named_substring(code,
            subject, ovector,
            stringcount, stringname,
            buffer, buffersize);
}			

int CPYSBSTR(const char *subject, int *ovector,
            int stringcount, int stringnumber, char *buffer,
            int buffersize)
{
       return pcre_copy_substring(subject, ovector,
            stringcount, stringnumber, buffer,
            buffersize);
}
			
int GETNMSBS(const pcre *code,
            const char *subject, int *ovector,
            int stringcount, const char *stringname,
            const char **stringptr)
{
       return pcre_get_named_substring(code,
            subject, ovector,
            stringcount, stringname,
            stringptr);
}
			
int GETSTNMB(const pcre *code,
            const char *name)
{
       return pcre_get_stringnumber(code,
            name);
}
			
int GETSTTBE(const pcre *code,
            const char *name, char **first, char **last)			
{			
       return pcre_get_stringtable_entries(code,
            name, first, last);
}
			
int GETSBSTR(const char *subject, int *ovector,
            int stringcount, int stringnumber,
            const char **stringptr)
{			
       return pcre_get_substring(subject, ovector,
            stringcount, stringnumber,
            stringptr);
}

int GETSBSLS(const char *subject,
            int *ovector, int stringcount, const char ***listptr)
{			
       return pcre_get_substring_list(subject,
            ovector, stringcount, listptr);
}

void FRESBSTR(const char *stringptr)
{			
              pcre_free_substring(stringptr);
}

void FRESBSLS(const char **stringptr)
{
              pcre_free_substring_list(stringptr);
}

/*PCRE NATIVE API AUXILIARY FUNCTIONS*/

/*       = all JIT are not supported.  However they are ported to represent a
	   program stub*/

pcre_jit_stack *ALCJITST(int startsize, int maxsize)
{
	      return pcre_jit_stack_alloc(startsize, maxsize);
}

void FREJITST(pcre_jit_stack *stack)
{
              pcre_jit_stack_free(stack);
}

void ASGJITST(pcre_extra *extra,
            pcre_jit_callback callback, void *data)
{
              pcre_assign_jit_stack(extra,
            callback, data);
}

/*       => MAKETAB8
	   const unsigned char *pcre_maketables(void);*/

/*       => FULLINF8
	   int pcre_fullinfo(const pcre *code, const pcre_extra *extra,
            int what, void *where);*/

/*       => REFCOUN8
	   int pcre_refcount(pcre *code, int adjust);*/

/*       => CONFIG8
	   int pcre_config(int what, void *where);*/

/*       => VERSION8
	   const char *pcre_version(void);*/

/*	   = part of BYTEORD8 - supported as is via PGMNAME(LONGMIXED) */
int PT2HBTOR(pcre *code,
            pcre_extra *extra, const unsigned char *tables)
{
       return pcre_pattern_to_host_byte_order(code,
            extra, tables);
}
			
/*PCRE NATIVE API INDIRECTED FUNCTIONS*/

/* names would be PMALLOC, PFREE, PSMALLO, PSFREE, CALLOUT
   but i have to investigate how to implement those */

/*       = all are part of GLOBALS8 - supported as is via PGMNAME(LONGMIXED) */
/*       void *(*pcre_malloc)(size_t);

       void (*pcre_free)(void *);

       void *(*pcre_stack_malloc)(size_t);

       void (*pcre_stack_free)(void *);

       int (*pcre_callout)(pcre_callout_block *);*/

/*SYNOPSIS OF POSIX API*/

/*      = not yet tested but should work!*/
/*	   note: native z/OS C has <regex.h> and these functions.  Do not issue
#include <regex.h> in any program that intend to use PCRE POSIX*/

int PREGCOMP(regex_t *preg, const char *pattern,
            int cflags)
{
       return regcomp(preg, pattern,
            cflags);
}

int PREGEXEC(regex_t *preg, const char *string,
            size_t nmatch, regmatch_t pmatch[], int eflags)
{
       return regexec(preg, string,
            nmatch, pmatch  , eflags);
}

size_t PREGERR(int errcode, const regex_t *preg,
            char *errbuf, size_t errbuf_size)
{
       return regerror(errcode, preg,
            errbuf, errbuf_size);
}

void PREGFREE(regex_t *preg)
{
              regfree(preg);
}

/*SYNOPSIS FOR PCRS API*/

/*       = not yet implemented but is planned*/
/*#include <pcrs.h>

       pcrs_job *pcrs_compile(const char * pattern ,
             const char * substitute , const char * options ,
             int * errptr );


       pcrs_job *pcrs_compile_command(const char * command ,
             int * errptr );


       int pcrs_execute(pcrs_job * job , char * subject ,
             int  subject_length , char ** result ,
             int * result_length );


       int pcrs_execute_list (pcrs_job * joblist , char * subject ,
              int  subject_length , char ** result ,
              int * result_length );


       pcrs_job *pcrs_free_job(pcrs_job * job );


       void pcrs_free_joblist(pcrs_job * joblist );


       char *pcrs_strerror(int  err );*/

/*SYNOPSIS FOR PCRZ API*/

/*	   = part of pcrzfunc - supported as is via PGMNAME(LONGMIXED) */

int ZWHTTRM (char * str, int maxlen)
{
       return pcrz_what_term_str (str, maxlen);
}

int ZISSPTRM (char * str, int maxlen)
{	
       return pcrz_is_space_term_str (str, maxlen);
}

int ZISNLTRM (char * str, int maxlen)
{	
       return pcrz_is_null_term_str (str, maxlen);
}

int ZSPC2NUL (char * str, int maxlen)
{	
       return pcrz_space_to_null_term_str (str, maxlen);
}

int ZNUL2SPC (char * str, int maxlen)
{	
       return pcrz_null_to_space_term_str (str, maxlen);
}
/*autoconv-0001 C:\projects\pcreport\pcobapi.c converted to PCOBAPI*/
./ ADD NAME=STRINGP8 
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wilsonh@google.com (Wilson Hsieh)
//

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <iostream>
#include "INTERNAP.h"
#include "pcre_stringpiece.h"

std::ostream& operator<<(std::ostream& o, const PCRECPP::StringPiece& piece) {
  return (o << piece.as_string());
}
/*autoconv-0001 C:\projects\pcre-8.31\pcre_stringpiece.cc converted to STRINGP8*/
/*autoconv-0010 STRINGP8 line: 34 added HAVE_CONFIG_H*/
/*autoconv-0011 STRINGP8 line: 37 config.h replaced by CONFIG.h*/
/*autoconv-0011 STRINGP8 line: 41 pcrecpp_internal.h replaced by INTERNAP.h*/
/*autoconv-0013 STRINGP8 line: 44 pcrecpp replaced by PCRECPP*/
./ ADD NAME=PCRETEST 
/*************************************************
*             PCRE testing program               *
*************************************************/

/* This program was hacked up as a tester for PCRE. I really should have
written it more tidily in the first place. Will I ever learn? It has grown and
been extended and consequently is now rather, er, *very* untidy in places. The
addition of 16-bit support has made it even worse. :-(

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

/* This program now supports the testing of both the 8-bit and 16-bit PCRE
libraries in a single program. This is different from the modules such as
COMPILE8.c in the library itself, which are compiled separately for each
mode. If both modes are enabled, for example, COMPILE8.c is compiled twice
(the second time with COMPILE_PCRE16 defined). By contrast, PCRETEST.c is
compiled only once. Therefore, it must not make use of any of the macros from
pcre_internal.h that depend on COMPILE_PCRE8 or COMPILE_PCRE16. It does,
however, make use of SUPPORT_PCRE8 and SUPPORT_PCRE16 to ensure that it calls
only supported library functions. */

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <locale.h>
#include <errno.h>

/* Both libreadline and libedit are optionally supported. The user-supplied
original patch uses readline/readline.h for libedit, but in at least one system
it is installed as editline/readline.h, so the configuration code now looks for
that first, falling back to readline/readline.h. */

#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if defined(SUPPORT_LIBREADLINE)
#include <readline/readline.h>
#include <readline/history.h>
#else
#if defined(HAVE_EDITLINE_READLINE_H)
#include <editline/readline.h>
#else
#include <readline/readline.h>
#endif
#endif
#endif

/* A number of things vary for Windows builds. Originally, PCRETEST opened its
input and output without "b"; then I was told that "b" was needed in some
environments, so it was added for release 5.0 to both the input and output. (It
makes no difference on Unix-like systems.) Later I was told that it is wrong
for the input on Windows. I've now abstracted the modes into two macros that
are set here, to make it easier to fiddle with them, and removed "b" from the
input mode under Windows. */

#if defined(_WIN32) || defined(WIN32)
#include <io.h>                /* For _setmode() */
#include <fcntl.h>             /* For _O_BINARY */
#define INPUT_MODE   "r"
#define OUTPUT_MODE  "wb"

#ifndef isatty
#define isatty _isatty         /* This is what Windows calls them, I'm told, */
#endif                         /* though in some environments they seem to   */
                               /* be already defined, hence the #ifndefs.    */
#ifndef fileno
#define fileno _fileno
#endif

/* A user sent this fix for Borland Builder 5 under Windows. */

#ifdef __BORLANDC__
#define _setmode(handle, mode) setmode(handle, mode)
#endif

/* Not Windows */

#else
#include <sys/time.h>          /* These two includes are needed */
#include <sys/resource.h>      /* for setrlimit(). */
/* ZA - z/OS use simple w and r*/
#if defined NATIVE_ZOS
#define INPUT_MODE   "r"
#define OUTPUT_MODE  "w"
#else
#define INPUT_MODE   "rb"
#define OUTPUT_MODE  "wb"
#endif
#endif

#define PRIV(name) name

/* We have to include pcre_internal.h because we need the internal info for
displaying the results of STUDY8() and we also need to know about the
internal macros, structures, and other internal data values; PCRETEST has
"inside information" compared to a program that strictly follows the PCRE API.

Although pcre_internal.h does itself include pcre.h, we explicitly include it
here before pcre_internal.h so that the PCRE_EXP_xxx macros get set
appropriately for an application, not for building PCRE. */

#include "PCRE.h"

#if defined SUPPORT_PCRE16 && !defined SUPPORT_PCRE8
/* Configure internal macros to 16 bit mode. */
#define COMPILE_PCRE16
#endif

#include "INTERNA8.h"

/* The PRINTIN8() function, which prints the internal form of a compiled
regex, is held in a separate file so that (a) it can be compiled in either
8-bit or 16-bit mode, and (b) it can be #included directly in COMPILE8.c
when that is compiled in debug mode. */

#ifdef SUPPORT_PCRE8
void PRINTIN8(pcre *external_re, FILE *f, BOOL print_lengths);
#endif
#ifdef SUPPORT_PCRE16
void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths);
#endif

/* We need access to some of the data tables that PCRE uses. So as not to have
to keep two copies, we include the source file here, changing the names of the
external symbols to prevent clashes. */

#define PCRE_INCLUDED

#include "TABLES8.c"

/* The definition of the macro PRINTABLE, which determines whether to print an
output character as-is or as a hex value when showing compiled patterns, is
the same as in the printint.src file. We uses it here in cases when the locale
has not been explicitly changed, so as to get consistent output from systems
that differ in their output from isprint() even in the "C" locale. */

#ifdef EBCDIC
#define PRINTABLE(c) ((c) >= 64 && (c) < 255)
#else
#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
#endif

#define PRINTOK(c) (locale_set? isprint(c) : PRINTABLE(c))

/* Posix support is disabled in 16 bit only mode. */
#if defined SUPPORT_PCRE16 && !defined SUPPORT_PCRE8 && !defined NOPOSIX
#define NOPOSIX
#endif

/* It is possible to compile this test program without including support for
testing the POSIX interface, though this is not available via the standard
Makefile. */

#if !defined NOPOSIX
#include "POSIXH.h"
#endif

/* It is also possible, originally for the benefit of a version that was
imported into Exim, to build PCRETEST without support for UTF8 or UTF16 (define
NOUTF), without the interface to the DFA matcher (NODFA). In fact, we
automatically cut out the UTF support if PCRE is built without it. */

#ifndef SUPPORT_UTF
#ifndef NOUTF
#define NOUTF
#endif
#endif

/* To make the code a bit tidier for 8-bit and 16-bit support, we define macros
for all the pcre[16]_xxx functions (except pcre16_fullinfo, which is called
only from one place and is handled differently). I couldn't dream up any way of
using a single macro to do this in a generic way, because of the many different
argument requirements. We know that at least one of SUPPORT_PCRE8 and
SUPPORT_PCRE16 must be set. First define macros for each individual mode; then
use these in the definitions of generic macros.

**** Special note about the PCHARSxxx macros: the address of the string to be
printed is always given as two arguments: a base address followed by an offset.
The base address is cast to the correct data size for 8 or 16 bit data; the
offset is in units of this size. If the string were given as base+offset in one
argument, the casting might be incorrectly applied. */

#ifdef SUPPORT_PCRE8

#define PCHARS8(lv, p, offset, len, f) \
  lv = pchars((pcre_uint8 *)(p) + offset, len, f)

#define PCHARSV8(p, offset, len, f) \
  (void)pchars((pcre_uint8 *)(p) + offset, len, f)

#define READ_CAPTURE_NAME8(p, cn8, cn16, re) \
  p = read_capture_name8(p, cn8, re)

#define STRLEN8(p) ((int)strlen((char *)p))

#define SET_PCRE_CALLOUT8(callout) \
  pcre_callout = callout

#define PCRE_ASSIGN_JIT_STACK8(extra, callback, userdata) \
   pcre_assign_jit_stack(extra, callback, userdata)

#define PCRE_COMPILE8(re, pat, options, error, erroffset, tables) \
  re = COMPILE8((char *)pat, options, error, erroffset, tables)

#define PCRE_COPY_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \
    namesptr, cbuffer, size) \
  rc = pcre_copy_named_substring(re, (char *)bptr, offsets, count, \
    (char *)namesptr, cbuffer, size)

#define PCRE_COPY_SUBSTRING8(rc, bptr, offsets, count, i, cbuffer, size) \
  rc = pcre_copy_substring((char *)bptr, offsets, count, i, cbuffer, size)

#define PCRE_DFA_EXEC8(count, re, extra, bptr, len, start_offset, options, \
    offsets, size_offsets, workspace, size_workspace) \
  count = DFAEXEC8(re, extra, (char *)bptr, len, start_offset, options, \
    offsets, size_offsets, workspace, size_workspace)

#define PCRE_EXEC8(count, re, extra, bptr, len, start_offset, options, \
    offsets, size_offsets) \
  count = PCREXEC8(re, extra, (char *)bptr, len, start_offset, options, \
    offsets, size_offsets)

#define PCRE_FREE_STUDY8(extra) \
  pcre_free_study(extra)

#define PCRE_FREE_SUBSTRING8(substring) \
  pcre_free_substring(substring)

#define PCRE_FREE_SUBSTRING_LIST8(listptr) \
  pcre_free_substring_list(listptr)

#define PCRE_GET_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \
    getnamesptr, subsptr) \
  rc = pcre_get_named_substring(re, (char *)bptr, offsets, count, \
    (char *)getnamesptr, subsptr)

#define PCRE_GET_STRINGNUMBER8(n, rc, ptr) \
  n = pcre_get_stringnumber(re, (char *)ptr)

#define PCRE_GET_SUBSTRING8(rc, bptr, offsets, count, i, subsptr) \
  rc = pcre_get_substring((char *)bptr, offsets, count, i, subsptr)

#define PCRE_GET_SUBSTRING_LIST8(rc, bptr, offsets, count, listptr) \
  rc = pcre_get_substring_list((const char *)bptr, offsets, count, listptr)

#define PCRE_PATTERN_TO_HOST_BYTE_ORDER8(rc, re, extra, tables) \
  rc = pcre_pattern_to_host_byte_order(re, extra, tables)

#define PCRE_PRINTINT8(re, outfile, debug_lengths) \
  PRINTIN8(re, outfile, debug_lengths)

#define PCRE_STUDY8(extra, re, options, error) \
  extra = STUDY8(re, options, error)

#define PCRE_JIT_STACK_ALLOC8(startsize, maxsize) \
  pcre_jit_stack_alloc(startsize, maxsize)

#define PCRE_JIT_STACK_FREE8(stack) \
  pcre_jit_stack_free(stack)

#endif /* SUPPORT_PCRE8 */

/* -----------------------------------------------------------*/

#ifdef SUPPORT_PCRE16

#define PCHARS16(lv, p, offset, len, f) \
  lv = pchars16((PCRE_SPTR16)(p) + offset, len, f)

#define PCHARSV16(p, offset, len, f) \
  (void)pchars16((PCRE_SPTR16)(p) + offset, len, f)

#define READ_CAPTURE_NAME16(p, cn8, cn16, re) \
  p = read_capture_name16(p, cn16, re)

#define STRLEN16(p) ((int)strlen16((PCRE_SPTR16)p))

#define SET_PCRE_CALLOUT16(callout) \
  pcre16_callout = (int (*)(pcre16_callout_block *))callout

#define PCRE_ASSIGN_JIT_STACK16(extra, callback, userdata) \
  pcre16_assign_jit_stack((pcre16_extra *)extra, \
    (pcre16_jit_callback)callback, userdata)

#define PCRE_COMPILE16(re, pat, options, error, erroffset, tables) \
  re = (pcre *)pcre16_compile((PCRE_SPTR16)pat, options, error, erroffset, \
    tables)

#define PCRE_COPY_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \
    namesptr, cbuffer, size) \
  rc = pcre16_copy_named_substring((pcre16 *)re, (PCRE_SPTR16)bptr, offsets, \
    count, (PCRE_SPTR16)namesptr, (PCRE_UCHAR16 *)cbuffer, size/2)

#define PCRE_COPY_SUBSTRING16(rc, bptr, offsets, count, i, cbuffer, size) \
  rc = pcre16_copy_substring((PCRE_SPTR16)bptr, offsets, count, i, \
    (PCRE_UCHAR16 *)cbuffer, size/2)

#define PCRE_DFA_EXEC16(count, re, extra, bptr, len, start_offset, options, \
    offsets, size_offsets, workspace, size_workspace) \
  count = pcre16_dfa_exec((pcre16 *)re, (pcre16_extra *)extra, \
    (PCRE_SPTR16)bptr, len, start_offset, options, offsets, size_offsets, \
    workspace, size_workspace)

#define PCRE_EXEC16(count, re, extra, bptr, len, start_offset, options, \
    offsets, size_offsets) \
  count = pcre16_exec((pcre16 *)re, (pcre16_extra *)extra, (PCRE_SPTR16)bptr, \
    len, start_offset, options, offsets, size_offsets)

#define PCRE_FREE_STUDY16(extra) \
  pcre16_free_study((pcre16_extra *)extra)

#define PCRE_FREE_SUBSTRING16(substring) \
  pcre16_free_substring((PCRE_SPTR16)substring)

#define PCRE_FREE_SUBSTRING_LIST16(listptr) \
  pcre16_free_substring_list((PCRE_SPTR16 *)listptr)

#define PCRE_GET_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \
    getnamesptr, subsptr) \
  rc = pcre16_get_named_substring((pcre16 *)re, (PCRE_SPTR16)bptr, offsets, \
    count, (PCRE_SPTR16)getnamesptr, (PCRE_SPTR16 *)(void*)subsptr)

#define PCRE_GET_STRINGNUMBER16(n, rc, ptr) \
  n = pcre16_get_stringnumber(re, (PCRE_SPTR16)ptr)

#define PCRE_GET_SUBSTRING16(rc, bptr, offsets, count, i, subsptr) \
  rc = pcre16_get_substring((PCRE_SPTR16)bptr, offsets, count, i, \
    (PCRE_SPTR16 *)(void*)subsptr)

#define PCRE_GET_SUBSTRING_LIST16(rc, bptr, offsets, count, listptr) \
  rc = pcre16_get_substring_list((PCRE_SPTR16)bptr, offsets, count, \
    (PCRE_SPTR16 **)(void*)listptr)

#define PCRE_PATTERN_TO_HOST_BYTE_ORDER16(rc, re, extra, tables) \
  rc = pcre16_pattern_to_host_byte_order((pcre16 *)re, (pcre16_extra *)extra, \
    tables)

#define PCRE_PRINTINT16(re, outfile, debug_lengths) \
  pcre16_printint(re, outfile, debug_lengths)

#define PCRE_STUDY16(extra, re, options, error) \
  extra = (pcre_extra *)pcre16_study((pcre16 *)re, options, error)

#define PCRE_JIT_STACK_ALLOC16(startsize, maxsize) \
  (pcre_jit_stack *)pcre16_jit_stack_alloc(startsize, maxsize)

#define PCRE_JIT_STACK_FREE16(stack) \
  pcre16_jit_stack_free((pcre16_jit_stack *)stack)

#endif /* SUPPORT_PCRE16 */


/* ----- Both modes are supported; a runtime test is needed, except for
CONFIG8(), and the JIT stack functions, when it doesn't matter which
version is called. ----- */

#if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16

#define CHAR_SIZE (use_pcre16? 2:1)

#define PCHARS(lv, p, offset, len, f) \
  if (use_pcre16) \
    PCHARS16(lv, p, offset, len, f); \
  else \
    PCHARS8(lv, p, offset, len, f)

#define PCHARSV(p, offset, len, f) \
  if (use_pcre16) \
    PCHARSV16(p, offset, len, f); \
  else \
    PCHARSV8(p, offset, len, f)

#define READ_CAPTURE_NAME(p, cn8, cn16, re) \
  if (use_pcre16) \
    READ_CAPTURE_NAME16(p, cn8, cn16, re); \
  else \
    READ_CAPTURE_NAME8(p, cn8, cn16, re)

#define SET_PCRE_CALLOUT(callout) \
  if (use_pcre16) \
    SET_PCRE_CALLOUT16(callout); \
  else \
    SET_PCRE_CALLOUT8(callout)

#define STRLEN(p) (use_pcre16? STRLEN16(p) : STRLEN8(p))

#define PCRE_ASSIGN_JIT_STACK(extra, callback, userdata) \
  if (use_pcre16) \
    PCRE_ASSIGN_JIT_STACK16(extra, callback, userdata); \
  else \
    PCRE_ASSIGN_JIT_STACK8(extra, callback, userdata)

#define PCRE_COMPILE(re, pat, options, error, erroffset, tables) \
  if (use_pcre16) \
    PCRE_COMPILE16(re, pat, options, error, erroffset, tables); \
  else \
    PCRE_COMPILE8(re, pat, options, error, erroffset, tables)

#define PCRE_CONFIG CONFIG8

#define PCRE_COPY_NAMED_SUBSTRING(rc, re, bptr, offsets, count, \
    namesptr, cbuffer, size) \
  if (use_pcre16) \
    PCRE_COPY_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \
      namesptr, cbuffer, size); \
  else \
    PCRE_COPY_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \
      namesptr, cbuffer, size)

#define PCRE_COPY_SUBSTRING(rc, bptr, offsets, count, i, cbuffer, size) \
  if (use_pcre16) \
    PCRE_COPY_SUBSTRING16(rc, bptr, offsets, count, i, cbuffer, size); \
  else \
    PCRE_COPY_SUBSTRING8(rc, bptr, offsets, count, i, cbuffer, size)

#define PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset, options, \
    offsets, size_offsets, workspace, size_workspace) \
  if (use_pcre16) \
    PCRE_DFA_EXEC16(count, re, extra, bptr, len, start_offset, options, \
      offsets, size_offsets, workspace, size_workspace); \
  else \
    PCRE_DFA_EXEC8(count, re, extra, bptr, len, start_offset, options, \
      offsets, size_offsets, workspace, size_workspace)

#define PCRE_EXEC(count, re, extra, bptr, len, start_offset, options, \
    offsets, size_offsets) \
  if (use_pcre16) \
    PCRE_EXEC16(count, re, extra, bptr, len, start_offset, options, \
      offsets, size_offsets); \
  else \
    PCRE_EXEC8(count, re, extra, bptr, len, start_offset, options, \
      offsets, size_offsets)

#define PCRE_FREE_STUDY(extra) \
  if (use_pcre16) \
    PCRE_FREE_STUDY16(extra); \
  else \
    PCRE_FREE_STUDY8(extra)

#define PCRE_FREE_SUBSTRING(substring) \
  if (use_pcre16) \
    PCRE_FREE_SUBSTRING16(substring); \
  else \
    PCRE_FREE_SUBSTRING8(substring)

#define PCRE_FREE_SUBSTRING_LIST(listptr) \
  if (use_pcre16) \
    PCRE_FREE_SUBSTRING_LIST16(listptr); \
  else \
    PCRE_FREE_SUBSTRING_LIST8(listptr)

#define PCRE_GET_NAMED_SUBSTRING(rc, re, bptr, offsets, count, \
    getnamesptr, subsptr) \
  if (use_pcre16) \
    PCRE_GET_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \
      getnamesptr, subsptr); \
  else \
    PCRE_GET_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \
      getnamesptr, subsptr)

#define PCRE_GET_STRINGNUMBER(n, rc, ptr) \
  if (use_pcre16) \
    PCRE_GET_STRINGNUMBER16(n, rc, ptr); \
  else \
    PCRE_GET_STRINGNUMBER8(n, rc, ptr)

#define PCRE_GET_SUBSTRING(rc, bptr, use_offsets, count, i, subsptr) \
  if (use_pcre16) \
    PCRE_GET_SUBSTRING16(rc, bptr, use_offsets, count, i, subsptr); \
  else \
    PCRE_GET_SUBSTRING8(rc, bptr, use_offsets, count, i, subsptr)

#define PCRE_GET_SUBSTRING_LIST(rc, bptr, offsets, count, listptr) \
  if (use_pcre16) \
    PCRE_GET_SUBSTRING_LIST16(rc, bptr, offsets, count, listptr); \
  else \
    PCRE_GET_SUBSTRING_LIST8(rc, bptr, offsets, count, listptr)

#define PCRE_JIT_STACK_ALLOC(startsize, maxsize) \
  (use_pcre16 ? \
     PCRE_JIT_STACK_ALLOC16(startsize, maxsize) \
    :PCRE_JIT_STACK_ALLOC8(startsize, maxsize))

#define PCRE_JIT_STACK_FREE(stack) \
  if (use_pcre16) \
    PCRE_JIT_STACK_FREE16(stack); \
  else \
    PCRE_JIT_STACK_FREE8(stack)

#define PCRE_MAKETABLES \
  (use_pcre16? pcre16_maketables() : MAKETAB8())

#define PCRE_PATTERN_TO_HOST_BYTE_ORDER(rc, re, extra, tables) \
  if (use_pcre16) \
    PCRE_PATTERN_TO_HOST_BYTE_ORDER16(rc, re, extra, tables); \
  else \
    PCRE_PATTERN_TO_HOST_BYTE_ORDER8(rc, re, extra, tables)

#define PCRE_PRINTINT(re, outfile, debug_lengths) \
  if (use_pcre16) \
    PCRE_PRINTINT16(re, outfile, debug_lengths); \
  else \
    PCRE_PRINTINT8(re, outfile, debug_lengths)

#define PCRE_STUDY(extra, re, options, error) \
  if (use_pcre16) \
    PCRE_STUDY16(extra, re, options, error); \
  else \
    PCRE_STUDY8(extra, re, options, error)

/* ----- Only 8-bit mode is supported ----- */

#elif defined SUPPORT_PCRE8
#define CHAR_SIZE                 1
#define PCHARS                    PCHARS8
#define PCHARSV                   PCHARSV8
#define READ_CAPTURE_NAME         READ_CAPTURE_NAME8
#define SET_PCRE_CALLOUT          SET_PCRE_CALLOUT8
#define STRLEN                    STRLEN8
#define PCRE_ASSIGN_JIT_STACK     PCRE_ASSIGN_JIT_STACK8
#define PCRE_COMPILE              PCRE_COMPILE8
#define PCRE_CONFIG               CONFIG8
#define PCRE_COPY_NAMED_SUBSTRING PCRE_COPY_NAMED_SUBSTRING8
#define PCRE_COPY_SUBSTRING       PCRE_COPY_SUBSTRING8
#define PCRE_DFA_EXEC             PCRE_DFA_EXEC8
#define PCRE_EXEC                 PCRE_EXEC8
#define PCRE_FREE_STUDY           PCRE_FREE_STUDY8
#define PCRE_FREE_SUBSTRING       PCRE_FREE_SUBSTRING8
#define PCRE_FREE_SUBSTRING_LIST  PCRE_FREE_SUBSTRING_LIST8
#define PCRE_GET_NAMED_SUBSTRING  PCRE_GET_NAMED_SUBSTRING8
#define PCRE_GET_STRINGNUMBER     PCRE_GET_STRINGNUMBER8
#define PCRE_GET_SUBSTRING        PCRE_GET_SUBSTRING8
#define PCRE_GET_SUBSTRING_LIST   PCRE_GET_SUBSTRING_LIST8
#define PCRE_JIT_STACK_ALLOC      PCRE_JIT_STACK_ALLOC8
#define PCRE_JIT_STACK_FREE       PCRE_JIT_STACK_FREE8
#define PCRE_MAKETABLES           MAKETAB8()
#define PCRE_PATTERN_TO_HOST_BYTE_ORDER PCRE_PATTERN_TO_HOST_BYTE_ORDER8
#define PCRE_PRINTINT             PCRE_PRINTINT8
#define PCRE_STUDY                PCRE_STUDY8

/* ----- Only 16-bit mode is supported ----- */

#else
#define CHAR_SIZE                 2
#define PCHARS                    PCHARS16
#define PCHARSV                   PCHARSV16
#define READ_CAPTURE_NAME         READ_CAPTURE_NAME16
#define SET_PCRE_CALLOUT          SET_PCRE_CALLOUT16
#define STRLEN                    STRLEN16
#define PCRE_ASSIGN_JIT_STACK     PCRE_ASSIGN_JIT_STACK16
#define PCRE_COMPILE              PCRE_COMPILE16
#define PCRE_CONFIG               pcre16_config
#define PCRE_COPY_NAMED_SUBSTRING PCRE_COPY_NAMED_SUBSTRING16
#define PCRE_COPY_SUBSTRING       PCRE_COPY_SUBSTRING16
#define PCRE_DFA_EXEC             PCRE_DFA_EXEC16
#define PCRE_EXEC                 PCRE_EXEC16
#define PCRE_FREE_STUDY           PCRE_FREE_STUDY16
#define PCRE_FREE_SUBSTRING       PCRE_FREE_SUBSTRING16
#define PCRE_FREE_SUBSTRING_LIST  PCRE_FREE_SUBSTRING_LIST16
#define PCRE_GET_NAMED_SUBSTRING  PCRE_GET_NAMED_SUBSTRING16
#define PCRE_GET_STRINGNUMBER     PCRE_GET_STRINGNUMBER16
#define PCRE_GET_SUBSTRING        PCRE_GET_SUBSTRING16
#define PCRE_GET_SUBSTRING_LIST   PCRE_GET_SUBSTRING_LIST16
#define PCRE_JIT_STACK_ALLOC      PCRE_JIT_STACK_ALLOC16
#define PCRE_JIT_STACK_FREE       PCRE_JIT_STACK_FREE16
#define PCRE_MAKETABLES           pcre16_maketables()
#define PCRE_PATTERN_TO_HOST_BYTE_ORDER PCRE_PATTERN_TO_HOST_BYTE_ORDER16
#define PCRE_PRINTINT             PCRE_PRINTINT16
#define PCRE_STUDY                PCRE_STUDY16
#endif

/* ----- End of mode-specific function call macros ----- */


/* Other parameters */

#ifndef CLOCKS_PER_SEC
#ifdef CLK_TCK
#define CLOCKS_PER_SEC CLK_TCK
#else
#define CLOCKS_PER_SEC 100
#endif
#endif

#if !defined NODFA
#define DFA_WS_DIMENSION 1000
#endif

/* This is the default loop count for timing. */

#define LOOPREPEAT 500000

/* Static variables */

static FILE *outfile;
static int log_store = 0;
static int callout_count;
static int callout_extra;
static int callout_fail_count;
static int callout_fail_id;
static int debug_lengths;
static int first_callout;
static int jit_was_used;
static int locale_set = 0;
static int show_malloc;
static int use_utf;
static size_t gotten_store;
static size_t first_gotten_store = 0;
static const unsigned char *last_callout_mark = NULL;

/* The buffers grow automatically if very long input lines are encountered. */

static int buffer_size = 50000;
static pcre_uint8 *buffer = NULL;
static pcre_uint8 *dbuffer = NULL;
static pcre_uint8 *pbuffer = NULL;

/* Another buffer is needed translation to 16-bit character strings. It will
obtained and extended as required. */

#ifdef SUPPORT_PCRE16
static int buffer16_size = 0;
static pcre_uint16 *buffer16 = NULL;

#ifdef SUPPORT_PCRE8

/* We need the table of operator lengths that is used for 16-bit compiling, in
order to swap bytes in a pattern for saving/reloading testing. Luckily, the
data is defined as a macro. However, we must ensure that LINK_SIZE is adjusted
appropriately for the 16-bit world. Just as a safety check, make sure that
COMPILE_PCRE16 is *not* set. */

#ifdef COMPILE_PCRE16
#error COMPILE_PCRE16 must not be set when compiling PCRETEST.c
#endif

#if LINK_SIZE == 2
#undef LINK_SIZE
#define LINK_SIZE 1
#elif LINK_SIZE == 3 || LINK_SIZE == 4
#undef LINK_SIZE
#define LINK_SIZE 2
#else
#error LINK_SIZE must be either 2, 3, or 4
#endif

#undef IMM2_SIZE
#define IMM2_SIZE 1

#endif /* SUPPORT_PCRE8 */

static const pcre_uint16 OP_lengths16[] = { OP_LENGTHS };
#endif  /* SUPPORT_PCRE16 */

/* If we have 8-bit support, default use_pcre16 to false; if there is also
16-bit support, it can be changed by an option. If there is no 8-bit support,
there must be 16-bit support, so default it to 1. */

#ifdef SUPPORT_PCRE8
static int use_pcre16 = 0;
#else
static int use_pcre16 = 1;
#endif

/* JIT study options for -s+n and /S+n where '1' <= n <= '7'. */

static int jit_study_bits[] =
  {
  PCRE_STUDY_JIT_COMPILE,
  PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE,
  PCRE_STUDY_JIT_COMPILE + PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE,
  PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE,
  PCRE_STUDY_JIT_COMPILE + PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE,
  PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE + PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE,
  PCRE_STUDY_JIT_COMPILE + PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE +
    PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
};

/* Textual explanations for runtime error codes */

static const char *errtexts[] = {
  NULL,  /* 0 is no error */
  NULL,  /* NOMATCH is handled specially */
  "NULL argument passed",
  "bad option value",
  "magic number missing",
  "unknown opcode - pattern overwritten?",
  "no more memory",
  NULL,  /* never returned by PCREXEC8() or DFAEXEC8() */
  "match limit exceeded",
  "callout error code",
  NULL,  /* BADUTF8/16 is handled specially */
  NULL,  /* BADUTF8/16 offset is handled specially */
  NULL,  /* PARTIAL is handled specially */
  "not used - internal error",
  "internal error - pattern overwritten?",
  "bad count value",
  "item unsupported for DFA matching",
  "backreference condition or recursion test not supported for DFA matching",
  "match limit not supported for DFA matching",
  "workspace size exceeded in DFA matching",
  "too much recursion for DFA matching",
  "recursion limit exceeded",
  "not used - internal error",
  "invalid combination of newline options",
  "bad offset value",
  NULL,  /* SHORTUTF8/16 is handled specially */
  "nested recursion at the same subject position",
  "JIT stack limit reached",
  "pattern compiled in wrong mode: 8-bit/16-bit error",
  "pattern compiled with other endianness",
  "invalid data in workspace for DFA restart"
};


/*************************************************
*         Alternate character tables             *
*************************************************/

/* By default, the "tables" pointer when calling PCRE is set to NULL, thereby
using the default tables of the library. However, the T option can be used to
select alternate sets of tables, for different kinds of testing. Note also that
the L (locale) option also adjusts the tables. */

/* This is the set of tables distributed as default with PCRE. It recognizes
only ASCII characters. */

static const pcre_uint8 tables0[] = {

/* This table is a lower casing table. */

    0,  1,  2,  3,  4,  5,  6,  7,
    8,  9, 10, 11, 12, 13, 14, 15,
   16, 17, 18, 19, 20, 21, 22, 23,
   24, 25, 26, 27, 28, 29, 30, 31,
   32, 33, 34, 35, 36, 37, 38, 39,
   40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55,
   56, 57, 58, 59, 60, 61, 62, 63,
   64, 97, 98, 99,100,101,102,103,
  104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,
  120,121,122, 91, 92, 93, 94, 95,
   96, 97, 98, 99,100,101,102,103,
  104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,
  120,121,122,123,124,125,126,127,
  128,129,130,131,132,133,134,135,
  136,137,138,139,140,141,142,143,
  144,145,146,147,148,149,150,151,
  152,153,154,155,156,157,158,159,
  160,161,162,163,164,165,166,167,
  168,169,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,
  184,185,186,187,188,189,190,191,
  192,193,194,195,196,197,198,199,
  200,201,202,203,204,205,206,207,
  208,209,210,211,212,213,214,215,
  216,217,218,219,220,221,222,223,
  224,225,226,227,228,229,230,231,
  232,233,234,235,236,237,238,239,
  240,241,242,243,244,245,246,247,
  248,249,250,251,252,253,254,255,

/* This table is a case flipping table. */

    0,  1,  2,  3,  4,  5,  6,  7,
    8,  9, 10, 11, 12, 13, 14, 15,
   16, 17, 18, 19, 20, 21, 22, 23,
   24, 25, 26, 27, 28, 29, 30, 31,
   32, 33, 34, 35, 36, 37, 38, 39,
   40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55,
   56, 57, 58, 59, 60, 61, 62, 63,
   64, 97, 98, 99,100,101,102,103,
  104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,
  120,121,122, 91, 92, 93, 94, 95,
   96, 65, 66, 67, 68, 69, 70, 71,
   72, 73, 74, 75, 76, 77, 78, 79,
   80, 81, 82, 83, 84, 85, 86, 87,
   88, 89, 90,123,124,125,126,127,
  128,129,130,131,132,133,134,135,
  136,137,138,139,140,141,142,143,
  144,145,146,147,148,149,150,151,
  152,153,154,155,156,157,158,159,
  160,161,162,163,164,165,166,167,
  168,169,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,
  184,185,186,187,188,189,190,191,
  192,193,194,195,196,197,198,199,
  200,201,202,203,204,205,206,207,
  208,209,210,211,212,213,214,215,
  216,217,218,219,220,221,222,223,
  224,225,226,227,228,229,230,231,
  232,233,234,235,236,237,238,239,
  240,241,242,243,244,245,246,247,
  248,249,250,251,252,253,254,255,

/* This table contains bit maps for various character classes. Each map is 32
bytes long and the bits run from the least significant end of each byte. The
classes that have their own maps are: space, xdigit, digit, upper, lower, word,
graph, print, punct, and cntrl. Other classes are built from combinations. */

  0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
  0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
  0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
  0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

/* This table identifies various classes of character by individual bits:
  0x01   white space character
  0x02   letter
  0x04   decimal digit
  0x08   hexadecimal digit
  0x10   alphanumeric or '_'
  0x80   regular expression metacharacter or binary zero
*/

  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7 */
  0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /*   8- 15 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  16- 23 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31 */
  0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /*    - '  */
  0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /*  ( - /  */
  0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /*  0 - 7  */
  0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /*  8 - ?  */
  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  @ - G  */
  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  H - O  */
  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  P - W  */
  0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /*  X - _  */
  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  ` - g  */
  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  h - o  */
  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  p - w  */
  0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /*  x -127 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */

/* This is a set of tables that came orginally from a Windows user. It seems to
be at least an approximation of ISO 8859. In particular, there are characters
greater than 128 that are marked as spaces, letters, etc. */

static const pcre_uint8 tables1[] = {
0,1,2,3,4,5,6,7,
8,9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,
24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,
40,41,42,43,44,45,46,47,
48,49,50,51,52,53,54,55,
56,57,58,59,60,61,62,63,
64,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122,91,92,93,94,95,
96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,
152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,215,
248,249,250,251,252,253,254,223,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255,
0,1,2,3,4,5,6,7,
8,9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,
24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,
40,41,42,43,44,45,46,47,
48,49,50,51,52,53,54,55,
56,57,58,59,60,61,62,63,
64,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122,91,92,93,94,95,
96,65,66,67,68,69,70,71,
72,73,74,75,76,77,78,79,
80,81,82,83,84,85,86,87,
88,89,90,123,124,125,126,127,
128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,
152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,215,
248,249,250,251,252,253,254,223,
192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,247,
216,217,218,219,220,221,222,255,
0,62,0,0,1,0,0,0,
0,0,0,0,0,0,0,0,
32,0,0,0,1,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,255,3,
126,0,0,0,126,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,255,3,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,12,2,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
254,255,255,7,0,0,0,0,
0,0,0,0,0,0,0,0,
255,255,127,127,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,254,255,255,7,
0,0,0,0,0,4,32,4,
0,0,0,128,255,255,127,255,
0,0,0,0,0,0,255,3,
254,255,255,135,254,255,255,7,
0,0,0,0,0,4,44,6,
255,255,127,255,255,255,127,255,
0,0,0,0,254,255,255,255,
255,255,255,255,255,255,255,127,
0,0,0,0,254,255,255,255,
255,255,255,255,255,255,255,255,
0,2,0,0,255,255,255,255,
255,255,255,255,255,255,255,127,
0,0,0,0,255,255,255,255,
255,255,255,255,255,255,255,255,
0,0,0,0,254,255,0,252,
1,0,0,248,1,0,0,120,
0,0,0,0,254,255,255,255,
0,0,128,0,0,0,128,0,
255,255,255,255,0,0,0,0,
0,0,0,0,0,0,0,128,
255,255,255,255,0,0,0,0,
0,0,0,0,0,0,0,0,
128,0,0,0,0,0,0,0,
0,1,1,0,1,1,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
1,0,0,0,128,0,0,0,
128,128,128,128,0,0,128,0,
28,28,28,28,28,28,28,28,
28,28,0,0,0,0,0,128,
0,26,26,26,26,26,26,18,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
18,18,18,128,128,0,128,16,
0,26,26,26,26,26,26,18,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
18,18,18,128,128,0,0,0,
0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,
0,0,18,0,0,0,0,0,
0,0,20,20,0,18,0,0,
0,20,18,0,0,0,0,0,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,0,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,0,
18,18,18,18,18,18,18,18
};




#ifndef HAVE_STRERROR
/*************************************************
*     Provide strerror() for non-ANSI libraries  *
*************************************************/

/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()
in their libraries, but can provide the same facility by this simple
alternative function. */

extern int   sys_nerr;
extern char *sys_errlist[];

char *
strerror(int n)
{
if (n < 0 || n >= sys_nerr) return "unknown error number";
return sys_errlist[n];
}
#endif /* HAVE_STRERROR */


/*************************************************
*         JIT memory callback                    *
*************************************************/

static pcre_jit_stack* jit_callback(void *arg)
{
jit_was_used = TRUE;
return (pcre_jit_stack *)arg;
}


#if !defined NOUTF || defined SUPPORT_PCRE16
/*************************************************
*            Convert UTF-8 string to value       *
*************************************************/

/* This function takes one or more bytes that represents a UTF-8 character,
and returns the value of the character.

Argument:
  utf8bytes   a pointer to the byte vector
  vptr        a pointer to an int to receive the value

Returns:      >  0 => the number of bytes consumed
              -6 to 0 => malformed UTF-8 character at offset = (-return)
*/

static int
utf82ord(pcre_uint8 *utf8bytes, int *vptr)
{
int c = *utf8bytes++;
int d = c;
int i, j, s;

for (i = -1; i < 6; i++)               /* i is number of additional bytes */
  {
  if ((d & 0x80) == 0) break;
  d <<= 1;
  }

if (i == -1) { *vptr = c; return 1; }  /* ascii character */
if (i == 0 || i == 6) return 0;        /* invalid UTF-8 */

/* i now has a value in the range 1-5 */

s = 6*i;
d = (c & utf8_table3[i]) << s;

for (j = 0; j < i; j++)
  {
  c = *utf8bytes++;
  if ((c & 0xc0) != 0x80) return -(j+1);
  s -= 6;
  d |= (c & 0x3f) << s;
  }

/* Check that encoding was the correct unique one */

for (j = 0; j < utf8_table1_size; j++)
  if (d <= utf8_table1[j]) break;
if (j != i) return -(i+1);

/* Valid value */

*vptr = d;
return i+1;
}
#endif /* NOUTF || SUPPORT_PCRE16 */



#if !defined NOUTF || defined SUPPORT_PCRE16
/*************************************************
*       Convert character value to UTF-8         *
*************************************************/

/* This function takes an integer value in the range 0 - 0x7fffffff
and encodes it as a UTF-8 character in 0 to 6 bytes.

Arguments:
  cvalue     the character value
  utf8bytes  pointer to buffer for result - at least 6 bytes long

Returns:     number of characters placed in the buffer
*/

static int
ord2utf8(int cvalue, pcre_uint8 *utf8bytes)
{
register int i, j;
for (i = 0; i < utf8_table1_size; i++)
  if (cvalue <= utf8_table1[i]) break;
utf8bytes += i;
for (j = i; j > 0; j--)
 {
 *utf8bytes-- = 0x80 | (cvalue & 0x3f);
 cvalue >>= 6;
 }
*utf8bytes = utf8_table2[i] | cvalue;
return i + 1;
}
#endif


#ifdef SUPPORT_PCRE16
/*************************************************
*         Convert a string to 16-bit             *
*************************************************/

/* In non-UTF mode, the space needed for a 16-bit string is exactly double the
8-bit size. For a UTF-8 string, the size needed for UTF-16 is no more than
double, because up to 0xffff uses no more than 3 bytes in UTF-8 but possibly 4
in UTF-16. Higher values use 4 bytes in UTF-8 and up to 4 bytes in UTF-16. The
result is always left in buffer16.

Note that this function does not object to surrogate values. This is
deliberate; it makes it possible to construct UTF-16 strings that are invalid,
for the purpose of testing that they are correctly faulted.

Patterns to be converted are either plain ASCII or UTF-8; data lines are always
in UTF-8 so that values greater than 255 can be handled.

Arguments:
  data       TRUE if converting a data line; FALSE for a regex
  p          points to a byte string
  utf        true if UTF-8 (to be converted to UTF-16)
  len        number of bytes in the string (excluding trailing zero)

Returns:     number of 16-bit data items used (excluding trailing zero)
             OR -1 if a UTF-8 string is malformed
             OR -2 if a value > 0x10ffff is encountered
             OR -3 if a value > 0xffff is encountered when not in UTF mode
*/

static int
to16(int data, pcre_uint8 *p, int utf, int len)
{
pcre_uint16 *pp;

if (buffer16_size < 2*len + 2)
  {
  if (buffer16 != NULL) free(buffer16);
  buffer16_size = 2*len + 2;
  buffer16 = (pcre_uint16 *)malloc(buffer16_size);
  if (buffer16 == NULL)
    {
    fprintf(stderr, "PCRETEST: malloc(%d) failed for buffer16\n", buffer16_size);
    exit(1);
    }
  }

pp = buffer16;

if (!utf && !data)
  {
  while (len-- > 0) *pp++ = *p++;
  }

else
  {
  int c = 0;
  while (len > 0)
    {
    int chlen = utf82ord(p, &c);
    if (chlen <= 0) return -1;
    if (c > 0x10ffff) return -2;
    p += chlen;
    len -= chlen;
    if (c < 0x10000) *pp++ = c; else
      {
      if (!utf) return -3;
      c -= 0x10000;
      *pp++ = 0xD800 | (c >> 10);
      *pp++ = 0xDC00 | (c & 0x3ff);
      }
    }
  }

*pp = 0;
return pp - buffer16;
}
#endif


/*************************************************
*        Read or extend an input line            *
*************************************************/

/* Input lines are read into buffer, but both patterns and data lines can be
continued over multiple input lines. In addition, if the buffer fills up, we
want to automatically expand it so as to be able to handle extremely large
lines that are needed for certain stress tests. When the input buffer is
expanded, the other two buffers must also be expanded likewise, and the
contents of pbuffer, which are a copy of the input for callouts, must be
preserved (for when expansion happens for a data line). This is not the most
optimal way of handling this, but hey, this is just a test program!

Arguments:
  f            the file to read
  start        where in buffer to start (this *must* be within buffer)
  prompt       for stdin or readline()

Returns:       pointer to the start of new data
               could be a copy of start, or could be moved
               NULL if no data read and EOF reached
*/

static pcre_uint8 *
extend_inputline(FILE *f, pcre_uint8 *start, const char *prompt)
{
pcre_uint8 *here = start;

for (;;)
  {
  size_t rlen = (size_t)(buffer_size - (here - buffer));

  if (rlen > 1000)
    {
    int dlen;

    /* If libreadline or libedit support is required, use readline() to read a
    line if the input is a terminal. Note that readline() removes the trailing
    newline, so we must put it back again, to be compatible with fgets(). */

#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)
    if (isatty(fileno(f)))
      {
      size_t len;
      char *s = readline(prompt);
      if (s == NULL) return (here == start)? NULL : start;
      len = strlen(s);
      if (len > 0) add_history(s);
      if (len > rlen - 1) len = rlen - 1;
      memcpy(here, s, len);
      here[len] = '\n';
      here[len+1] = 0;
      free(s);
      }
    else
#endif

    /* Read the next line by normal means, prompting if the file is stdin. */

      {
      if (f == stdin) printf("%s", prompt);
      if (fgets((char *)here, rlen,  f) == NULL)
        return (here == start)? NULL : start;
      }

    dlen = (int)strlen((char *)here);
    if (dlen > 0 && here[dlen - 1] == '\n') return start;
    here += dlen;
    }

  else
    {
    int new_buffer_size = 2*buffer_size;
    pcre_uint8 *new_buffer = (pcre_uint8 *)malloc(new_buffer_size);
    pcre_uint8 *new_dbuffer = (pcre_uint8 *)malloc(new_buffer_size);
    pcre_uint8 *new_pbuffer = (pcre_uint8 *)malloc(new_buffer_size);

    if (new_buffer == NULL || new_dbuffer == NULL || new_pbuffer == NULL)
      {
      fprintf(stderr, "PCRETEST: malloc(%d) failed\n", new_buffer_size);
      exit(1);
      }

    memcpy(new_buffer, buffer, buffer_size);
    memcpy(new_pbuffer, pbuffer, buffer_size);

    buffer_size = new_buffer_size;

    start = new_buffer + (start - buffer);
    here = new_buffer + (here - buffer);

    free(buffer);
    free(dbuffer);
    free(pbuffer);

    buffer = new_buffer;
    dbuffer = new_dbuffer;
    pbuffer = new_pbuffer;
    }
  }

return NULL;  /* Control never gets here */
}



/*************************************************
*          Read number from string               *
*************************************************/

/* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess
around with conditional compilation, just do the job by hand. It is only used
for unpicking arguments, so just keep it simple.

Arguments:
  str           string to be converted
  endptr        where to put the end pointer

Returns:        the unsigned long
*/

static int
get_value(pcre_uint8 *str, pcre_uint8 **endptr)
{
int result = 0;
while(*str != 0 && isspace(*str)) str++;
while (isdigit(*str)) result = result * 10 + (int)(*str++ - '0');
*endptr = str;
return(result);
}



/*************************************************
*             Print one character                *
*************************************************/

/* Print a single character either literally, or as a hex escape. */

static int pchar(int c, FILE *f)
{
if (PRINTOK(c))
  {
  if (f != NULL) fprintf(f, "%c", c);
  return 1;
  }

if (c < 0x100)
  {
  if (use_utf)
    {
    if (f != NULL) fprintf(f, "\\x{%02x}", c);
    return 6;
    }
  else
    {
    if (f != NULL) fprintf(f, "\\x%02x", c);
    return 4;
    }
  }

if (f != NULL) fprintf(f, "\\x{%02x}", c);
return (c <= 0x000000ff)? 6 :
       (c <= 0x00000fff)? 7 :
       (c <= 0x0000ffff)? 8 :
       (c <= 0x000fffff)? 9 : 10;
}



#ifdef SUPPORT_PCRE8
/*************************************************
*         Print 8-bit character string           *
*************************************************/

/* Must handle UTF-8 strings in utf8 mode. Yields number of characters printed.
If handed a NULL file, just counts chars without printing. */

static int pchars(pcre_uint8 *p, int length, FILE *f)
{
int c = 0;
int yield = 0;

if (length < 0)
  length = strlen((char *)p);

while (length-- > 0)
  {
#if !defined NOUTF
  if (use_utf)
    {
    int rc = utf82ord(p, &c);
    if (rc > 0 && rc <= length + 1)   /* Mustn't run over the end */
      {
      length -= rc - 1;
      p += rc;
      yield += pchar(c, f);
      continue;
      }
    }
#endif
  c = *p++;
  yield += pchar(c, f);
  }

return yield;
}
#endif



#ifdef SUPPORT_PCRE16
/*************************************************
*    Find length of 0-terminated 16-bit string   *
*************************************************/

static int strlen16(PCRE_SPTR16 p)
{
int len = 0;
while (*p++ != 0) len++;
return len;
}
#endif  /* SUPPORT_PCRE16 */


#ifdef SUPPORT_PCRE16
/*************************************************
*           Print 16-bit character string        *
*************************************************/

/* Must handle UTF-16 strings in utf mode. Yields number of characters printed.
If handed a NULL file, just counts chars without printing. */

static int pchars16(PCRE_SPTR16 p, int length, FILE *f)
{
int yield = 0;

if (length < 0)
  length = strlen16(p);

while (length-- > 0)
  {
  int c = *p++ & 0xffff;
#if !defined NOUTF
  if (use_utf && c >= 0xD800 && c < 0xDC00 && length > 0)
    {
    int d = *p & 0xffff;
    if (d >= 0xDC00 && d < 0xDFFF)
      {
      c = ((c & 0x3ff) << 10) + (d & 0x3ff) + 0x10000;
      length--;
      p++;
      }
    }
#endif
  yield += pchar(c, f);
  }

return yield;
}
#endif  /* SUPPORT_PCRE16 */



#ifdef SUPPORT_PCRE8
/*************************************************
*     Read a capture name (8-bit) and check it   *
*************************************************/

static pcre_uint8 *
read_capture_name8(pcre_uint8 *p, pcre_uint8 **pp, pcre *re)
{
pcre_uint8 *npp = *pp;
while (isalnum(*p)) *npp++ = *p++;
*npp++ = 0;
*npp = 0;
if (pcre_get_stringnumber(re, (char *)(*pp)) < 0)
  {
  fprintf(outfile, "no parentheses with name \"");
  PCHARSV(*pp, 0, -1, outfile);
  fprintf(outfile, "\"\n");
  }

*pp = npp;
return p;
}
#endif  /* SUPPORT_PCRE8 */



#ifdef SUPPORT_PCRE16
/*************************************************
*     Read a capture name (16-bit) and check it  *
*************************************************/

/* Note that the text being read is 8-bit. */

static pcre_uint8 *
read_capture_name16(pcre_uint8 *p, pcre_uint16 **pp, pcre *re)
{
pcre_uint16 *npp = *pp;
while (isalnum(*p)) *npp++ = *p++;
*npp++ = 0;
*npp = 0;
if (pcre16_get_stringnumber((pcre16 *)re, (PCRE_SPTR16)(*pp)) < 0)
  {
  fprintf(outfile, "no parentheses with name \"");
  PCHARSV(*pp, 0, -1, outfile);
  fprintf(outfile, "\"\n");
  }
*pp = npp;
return p;
}
#endif  /* SUPPORT_PCRE16 */



/*************************************************
*              Callout function                  *
*************************************************/

/* Called from PCRE as a result of the (?C) item. We print out where we are in
the match. Yield zero unless more callouts than the fail count, or the callout
data is not zero. */

static int callout(pcre_callout_block *cb)
{
FILE *f = (first_callout | callout_extra)? outfile : NULL;
int i, pre_start, post_start, subject_length;

if (callout_extra)
  {
  fprintf(f, "Callout %d: last capture = %d\n",
    cb->callout_number, cb->capture_last);

  for (i = 0; i < cb->capture_top * 2; i += 2)
    {
    if (cb->offset_vector[i] < 0)
      fprintf(f, "%2d: <unset>\n", i/2);
    else
      {
      fprintf(f, "%2d: ", i/2);
      PCHARSV(cb->subject, cb->offset_vector[i],
        cb->offset_vector[i+1] - cb->offset_vector[i], f);
      fprintf(f, "\n");
      }
    }
  }

/* Re-print the subject in canonical form, the first time or if giving full
datails. On subsequent calls in the same match, we use pchars just to find the
printed lengths of the substrings. */

if (f != NULL) fprintf(f, "--->");

PCHARS(pre_start, cb->subject, 0, cb->start_match, f);
PCHARS(post_start, cb->subject, cb->start_match,
  cb->current_position - cb->start_match, f);

PCHARS(subject_length, cb->subject, 0, cb->subject_length, NULL);

PCHARSV(cb->subject, cb->current_position,
  cb->subject_length - cb->current_position, f);

if (f != NULL) fprintf(f, "\n");

/* Always print appropriate indicators, with callout number if not already
shown. For automatic callouts, show the pattern offset. */

if (cb->callout_number == 255)
  {
  fprintf(outfile, "%+3d ", cb->pattern_position);
  if (cb->pattern_position > 99) fprintf(outfile, "\n    ");
  }
else
  {
  if (callout_extra) fprintf(outfile, "    ");
    else fprintf(outfile, "%3d ", cb->callout_number);
  }

for (i = 0; i < pre_start; i++) fprintf(outfile, " ");
fprintf(outfile, "");

if (post_start > 0)
  {
  for (i = 0; i < post_start - 1; i++) fprintf(outfile, " ");
  fprintf(outfile, "");
  }

for (i = 0; i < subject_length - pre_start - post_start + 4; i++)
  fprintf(outfile, " ");

fprintf(outfile, "%.*s", (cb->next_item_length == 0)? 1 : cb->next_item_length,
  pbuffer + cb->pattern_position);

fprintf(outfile, "\n");
first_callout = 0;

if (cb->mark != last_callout_mark)
  {
  if (cb->mark == NULL)
    fprintf(outfile, "Latest Mark: <unset>\n");
  else
    {
    fprintf(outfile, "Latest Mark: ");
    PCHARSV(cb->mark, 0, -1, outfile);
    putc('\n', outfile);
    }
  last_callout_mark = cb->mark;
  }

if (cb->callout_data != NULL)
  {
  int callout_data = *((int *)(cb->callout_data));
  if (callout_data != 0)
    {
    fprintf(outfile, "Callout data = %d\n", callout_data);
    return callout_data;
    }
  }

return (cb->callout_number != callout_fail_id)? 0 :
       (++callout_count >= callout_fail_count)? 1 : 0;
}


/*************************************************
*            Local malloc functions              *
*************************************************/

/* Alternative malloc function, to test functionality and save the size of a
compiled re, which is the first store request that COMPILE8() makes. The
show_malloc variable is set only during matching. */

static void *new_malloc(size_t size)
{
void *block = malloc(size);
gotten_store = size;
if (first_gotten_store == 0) first_gotten_store = size;
if (show_malloc)
  fprintf(outfile, "malloc       %3d %p\n", (int)size, block);
return block;
}

static void new_free(void *block)
{
if (show_malloc)
  fprintf(outfile, "free             %p\n", block);
free(block);
}

/* For recursion malloc/free, to test stacking calls */

static void *stack_malloc(size_t size)
{
void *block = malloc(size);
if (show_malloc)
  fprintf(outfile, "stack_malloc %3d %p\n", (int)size, block);
return block;
}

static void stack_free(void *block)
{
if (show_malloc)
  fprintf(outfile, "stack_free       %p\n", block);
free(block);
}


/*************************************************
*          Call FULLINF8()                  *
*************************************************/

/* Get one piece of information from the FULLINF8() function. When only
one of 8-bit or 16-bit is supported, use_pcre16 should always have the correct
value, but the code is defensive.

Arguments:
  re        compiled regex
  study     study data
  option    PCRE_INFO_xxx option
  ptr       where to put the data

Returns:    0 when OK, < 0 on error
*/

static int
new_info(pcre *re, pcre_extra *study, int option, void *ptr)
{
int rc;

if (use_pcre16)
#ifdef SUPPORT_PCRE16
  rc = pcre16_fullinfo((pcre16 *)re, (pcre16_extra *)study, option, ptr);
#else
  rc = PCRE_ERROR_BADMODE;
#endif
else
#ifdef SUPPORT_PCRE8
  rc = FULLINF8(re, study, option, ptr);
#else
  rc = PCRE_ERROR_BADMODE;
#endif

if (rc < 0)
  {
  fprintf(outfile, "Error %d from pcre%s_fullinfo(%d)\n", rc,
    use_pcre16? "16" : "", option);
  if (rc == PCRE_ERROR_BADMODE)
    fprintf(outfile, "Running in %s-bit mode but pattern was compiled in "
      "%s-bit mode\n", use_pcre16? "16":"8", use_pcre16? "8":"16");
  }

return rc;
}



/*************************************************
*             Swap byte functions                *
*************************************************/

/* The following functions swap the bytes of a pcre_uint16 and pcre_uint32
value, respectively.

Arguments:
  value        any number

Returns:       the byte swapped value
*/

static pcre_uint32
swap_uint32(pcre_uint32 value)
{
return ((value & 0x000000ff) << 24) |
       ((value & 0x0000ff00) <<  8) |
       ((value & 0x00ff0000) >>  8) |
       (value >> 24);
}

static pcre_uint16
swap_uint16(pcre_uint16 value)
{
return (value >> 8) | (value << 8);
}



/*************************************************
*        Flip bytes in a compiled pattern        *
*************************************************/

/* This function is called if the 'F' option was present on a pattern that is
to be written to a file. We flip the bytes of all the integer fields in the
regex data block and the study block. In 16-bit mode this also flips relevant
bytes in the pattern itself. This is to make it possible to test PCRE's
ability to reload byte-flipped patterns, e.g. those compiled on a different
architecture. */

static void
regexflip(pcre *ere, pcre_extra *extra)
{
REAL_PCRE *re = (REAL_PCRE *)ere;
#ifdef SUPPORT_PCRE16
int op;
pcre_uint16 *ptr = (pcre_uint16 *)re + re->name_table_offset;
int length = re->name_count * re->name_entry_size;
#ifdef SUPPORT_UTF
BOOL utf = (re->options & PCRE_UTF16) != 0;
BOOL utf16_char = FALSE;
#endif /* SUPPORT_UTF */
#endif /* SUPPORT_PCRE16 */

/* Always flip the bytes in the main data block and study blocks. */

re->magic_number = REVERSED_MAGIC_NUMBER;
re->size = swap_uint32(re->size);
re->options = swap_uint32(re->options);
re->flags = swap_uint16(re->flags);
re->top_bracket = swap_uint16(re->top_bracket);
re->top_backref = swap_uint16(re->top_backref);
re->first_char = swap_uint16(re->first_char);
re->req_char = swap_uint16(re->req_char);
re->name_table_offset = swap_uint16(re->name_table_offset);
re->name_entry_size = swap_uint16(re->name_entry_size);
re->name_count = swap_uint16(re->name_count);

if (extra != NULL)
  {
  pcre_study_data *rsd = (pcre_study_data *)(extra->study_data);
  rsd->size = swap_uint32(rsd->size);
  rsd->flags = swap_uint32(rsd->flags);
  rsd->minlength = swap_uint32(rsd->minlength);
  }

/* In 8-bit mode, that is all we need to do. In 16-bit mode we must swap bytes
in the name table, if present, and then in the pattern itself. */

#ifdef SUPPORT_PCRE16
if (!use_pcre16) return;

while(TRUE)
  {
  /* Swap previous characters. */
  while (length-- > 0)
    {
    *ptr = swap_uint16(*ptr);
    ptr++;
    }
#ifdef SUPPORT_UTF
  if (utf16_char)
    {
    if ((ptr[-1] & 0xfc00) == 0xd800)
      {
      /* We know that there is only one extra character in UTF-16. */
      *ptr = swap_uint16(*ptr);
      ptr++;
      }
    }
  utf16_char = FALSE;
#endif /* SUPPORT_UTF */

  /* Get next opcode. */

  length = 0;
  op = *ptr;
  *ptr++ = swap_uint16(op);

  switch (op)
    {
    case OP_END:
    return;

#ifdef SUPPORT_UTF
    case OP_CHAR:
    case OP_CHARI:
    case OP_NOT:
    case OP_NOTI:
    case OP_STAR:
    case OP_MINSTAR:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_QUERY:
    case OP_MINQUERY:
    case OP_UPTO:
    case OP_MINUPTO:
    case OP_EXACT:
    case OP_POSSTAR:
    case OP_POSPLUS:
    case OP_POSQUERY:
    case OP_POSUPTO:
    case OP_STARI:
    case OP_MINSTARI:
    case OP_PLUSI:
    case OP_MINPLUSI:
    case OP_QUERYI:
    case OP_MINQUERYI:
    case OP_UPTOI:
    case OP_MINUPTOI:
    case OP_EXACTI:
    case OP_POSSTARI:
    case OP_POSPLUSI:
    case OP_POSQUERYI:
    case OP_POSUPTOI:
    case OP_NOTSTAR:
    case OP_NOTMINSTAR:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTQUERY:
    case OP_NOTMINQUERY:
    case OP_NOTUPTO:
    case OP_NOTMINUPTO:
    case OP_NOTEXACT:
    case OP_NOTPOSSTAR:
    case OP_NOTPOSPLUS:
    case OP_NOTPOSQUERY:
    case OP_NOTPOSUPTO:
    case OP_NOTSTARI:
    case OP_NOTMINSTARI:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUSI:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERYI:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTOI:
    case OP_NOTEXACTI:
    case OP_NOTPOSSTARI:
    case OP_NOTPOSPLUSI:
    case OP_NOTPOSQUERYI:
    case OP_NOTPOSUPTOI:
    if (utf) utf16_char = TRUE;
#endif
    /* Fall through. */

    default:
    length = OP_lengths16[op] - 1;
    break;

    case OP_CLASS:
    case OP_NCLASS:
    /* Skip the character bit map. */
    ptr += 32/sizeof(pcre_uint16);
    length = 0;
    break;

    case OP_XCLASS:
    /* LINK_SIZE can be 1 or 2 in 16 bit mode. */
    if (LINK_SIZE > 1)
      length = (int)((((unsigned int)(ptr[0]) << 16) | (unsigned int)(ptr[1]))
        - (1 + LINK_SIZE + 1));
    else
      length = (int)((unsigned int)(ptr[0]) - (1 + LINK_SIZE + 1));

    /* Reverse the size of the XCLASS instance. */
    *ptr = swap_uint16(*ptr);
    ptr++;
    if (LINK_SIZE > 1)
      {
      *ptr = swap_uint16(*ptr);
      ptr++;
      }

    op = *ptr;
    *ptr = swap_uint16(op);
    ptr++;
    if ((op & XCL_MAP) != 0)
      {
      /* Skip the character bit map. */
      ptr += 32/sizeof(pcre_uint16);
      length -= 32/sizeof(pcre_uint16);
      }
    break;
    }
  }
/* Control should never reach here in 16 bit mode. */
#endif /* SUPPORT_PCRE16 */
}



/*************************************************
*        Check match or recursion limit          *
*************************************************/

static int
check_match_limit(pcre *re, pcre_extra *extra, pcre_uint8 *bptr, int len,
  int start_offset, int options, int *use_offsets, int use_size_offsets,
  int flag, unsigned long int *limit, int errnumber, const char *msg)
{
int count;
int min = 0;
int mid = 64;
int max = -1;

extra->flags |= flag;

for (;;)
  {
  *limit = mid;

  PCRE_EXEC(count, re, extra, bptr, len, start_offset, options,
    use_offsets, use_size_offsets);

  if (count == errnumber)
    {
    /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */
    min = mid;
    mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2;
    }

  else if (count >= 0 || count == PCRE_ERROR_NOMATCH ||
                         count == PCRE_ERROR_PARTIAL)
    {
    if (mid == min + 1)
      {
      fprintf(outfile, "Minimum %s limit = %d\n", msg, mid);
      break;
      }
    /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */
    max = mid;
    mid = (min + mid)/2;
    }
  else break;    /* Some other error */
  }

extra->flags &= ~flag;
return count;
}



/*************************************************
*         Case-independent strncmp() function    *
*************************************************/

/*
Arguments:
  s         first string
  t         second string
  n         number of characters to compare

Returns:    < 0, = 0, or > 0, according to the comparison
*/

static int
strncmpic(pcre_uint8 *s, pcre_uint8 *t, int n)
{
while (n--)
  {
  int c = tolower(*s++) - tolower(*t++);
  if (c) return c;
  }
return 0;
}



/*************************************************
*         Check newline indicator                *
*************************************************/

/* This is used both at compile and run-time to check for <xxx> escapes. Print
a message and return 0 if there is no match.

Arguments:
  p           points after the leading '<'
  f           file for error message

Returns:      appropriate PCRE_NEWLINE_xxx flags, or 0
*/

static int
check_newline(pcre_uint8 *p, FILE *f)
{
if (strncmpic(p, (pcre_uint8 *)"cr>", 3) == 0) return PCRE_NEWLINE_CR;
if (strncmpic(p, (pcre_uint8 *)"lf>", 3) == 0) return PCRE_NEWLINE_LF;
if (strncmpic(p, (pcre_uint8 *)"crlf>", 5) == 0) return PCRE_NEWLINE_CRLF;
if (strncmpic(p, (pcre_uint8 *)"anycrlf>", 8) == 0) return PCRE_NEWLINE_ANYCRLF;
if (strncmpic(p, (pcre_uint8 *)"any>", 4) == 0) return PCRE_NEWLINE_ANY;
if (strncmpic(p, (pcre_uint8 *)"bsr_anycrlf>", 12) == 0) return PCRE_BSR_ANYCRLF;
if (strncmpic(p, (pcre_uint8 *)"bsr_unicode>", 12) == 0) return PCRE_BSR_UNICODE;
fprintf(f, "Unknown newline type at: <%s\n", p);
return 0;
}



/*************************************************
*             Usage function                     *
*************************************************/

static void
usage(void)
{
printf("Usage:     PCRETEST [options] [<input file> [<output file>]]\n\n");
printf("Input and output default to stdin and stdout.\n");
#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)
printf("If input is a terminal, readline() is used to read from it.\n");
#else
printf("This version of PCRETEST is not linked with readline().\n");
#endif
printf("\nOptions:\n");
#ifdef SUPPORT_PCRE16
printf("  -16      use the 16-bit library\n");
#endif
printf("  -b       show compiled code\n");
printf("  -C       show PCRE compile-time options and exit\n");
printf("  -C arg   show a specific compile-time option\n");
printf("           and exit with its value. The arg can be:\n");
printf("     linksize     internal link size [2, 3, 4]\n");
printf("     pcre8        8 bit library support enabled [0, 1]\n");
printf("     pcre16       16 bit library support enabled [0, 1]\n");
printf("     utf          Unicode Transformation Format supported [0, 1]\n");
printf("     ucp          Unicode Properties supported [0, 1]\n");
printf("     jit          Just-in-time compiler supported [0, 1]\n");
printf("     newline      Newline type [CR, LF, CRLF, ANYCRLF, ANY, ???]\n");
printf("  -d       debug: show compiled code and information (-b and -i)\n");
#if !defined NODFA
printf("  -dfa     force DFA matching for all subjects\n");
#endif
printf("  -help    show usage information\n");
printf("  -i       show information about compiled patterns\n"
       "  -M       find MATCH_LIMIT minimum for each subject\n"
       "  -m       output memory used information\n"
       "  -o <n>   set size of offsets vector to <n>\n");
#if !defined NOPOSIX
printf("  -p       use POSIX interface\n");
#endif
printf("  -q       quiet: do not output PCRE version number at start\n");
printf("  -S <n>   set stack size to <n> megabytes\n");
printf("  -s       force each pattern to be studied at basic level\n"
       "  -s+      force each pattern to be studied, using JIT if available\n"
       "  -s++     ditto, verifying when JIT was actually used\n"
       "  -s+n     force each pattern to be studied, using JIT if available,\n"
       "             where 1 <= n <= 7 selects JIT options\n"
       "  -s++n    ditto, verifying when JIT was actually used\n"
       "  -t       time compilation and execution\n");
printf("  -t <n>   time compilation and execution, repeating <n> times\n");
printf("  -tm      time execution (matching) only\n");
printf("  -tm <n>  time execution (matching) only, repeating <n> times\n");
}



/*************************************************
*                Main Program                    *
*************************************************/

/* Read lines from named file or stdin and write to named file or stdout; lines
consist of a regular expression, in delimiters and optionally followed by
options, followed by a set of test data, terminated by an empty line. */

int main(int argc, char **argv)
{
FILE *infile = stdin;
const char *version;
int options = 0;
int study_options = 0;
int default_find_match_limit = FALSE;
int op = 1;
int timeit = 0;
int timeitm = 0;
int showinfo = 0;
int showstore = 0;
int force_study = -1;
int force_study_options = 0;
int quiet = 0;
int size_offsets = 45;
int size_offsets_max;
int *offsets = NULL;
int debug = 0;
int done = 0;
int all_use_dfa = 0;
int verify_jit = 0;
int yield = 0;
int stack_size;

#if !defined NOPOSIX
int posix = 0;
#endif
#if !defined NODFA
int *dfa_workspace = NULL;
#endif

pcre_jit_stack *jit_stack = NULL;

/* These vectors store, end-to-end, a list of zero-terminated captured
substring names, each list itself being terminated by an empty name. Assume
that 1024 is plenty long enough for the few names we'll be testing. It is
easiest to keep separate 8-bit and 16-bit versions, using the 16-bit version
for the actual memory, to ensure alignment. */

pcre_uint16 copynames[1024];
pcre_uint16 getnames[1024];

#ifdef SUPPORT_PCRE16
pcre_uint16 *cn16ptr;
pcre_uint16 *gn16ptr;
#endif

#ifdef SUPPORT_PCRE8
pcre_uint8 *copynames8 = (pcre_uint8 *)copynames;
pcre_uint8 *getnames8 = (pcre_uint8 *)getnames;
pcre_uint8 *cn8ptr;
pcre_uint8 *gn8ptr;
#endif

/* Get buffers from malloc() so that valgrind will check their misuse when
debugging. They grow automatically when very long lines are read. The 16-bit
buffer (buffer16) is obtained only if needed. */

buffer = (pcre_uint8 *)malloc(buffer_size);
dbuffer = (pcre_uint8 *)malloc(buffer_size);
pbuffer = (pcre_uint8 *)malloc(buffer_size);

/* The outfile variable is static so that new_malloc can use it. */

outfile = stdout;

/* The following  _setmode() stuff is some Windows magic that tells its runtime
library to translate CRLF into a single LF character. At least, that's what
I've been told: never having used Windows I take this all on trust. Originally
it set 0x8000, but then I was advised that _O_BINARY was better. */

#if defined(_WIN32) || defined(WIN32)
_setmode( _fileno( stdout ), _O_BINARY );
#endif

/* Get the version number: both VERSION8() and pcre16_version() give the
same answer. We just need to ensure that we call one that is available. */

#ifdef SUPPORT_PCRE8
version = VERSION8();
#else
version = pcre16_version();
#endif

/* Scan options */

while (argc > 1 && argv[op][0] == '-')
  {
  pcre_uint8 *endptr;
  char *arg = argv[op];

  if (strcmp(arg, "-m") == 0) showstore = 1;
  else if (strcmp(arg, "-s") == 0) force_study = 0;

  else if (strncmp(arg, "-s+", 3) == 0)
    {
    arg += 3;
    if (*arg == '+') { arg++; verify_jit = TRUE; }
    force_study = 1;
    if (*arg == 0)
      force_study_options = jit_study_bits[6];
    else if (*arg >= '1' && *arg <= '7')
      force_study_options = jit_study_bits[*arg - '1'];
    else goto BAD_ARG;
    }
  else if (strcmp(arg, "-16") == 0)
    {
#ifdef SUPPORT_PCRE16
    use_pcre16 = 1;
#else
    printf("** This version of PCRE was built without 16-bit support\n");
    exit(1);
#endif
    }
  else if (strcmp(arg, "-q") == 0) quiet = 1;
  else if (strcmp(arg, "-b") == 0) debug = 1;
  else if (strcmp(arg, "-i") == 0) showinfo = 1;
  else if (strcmp(arg, "-d") == 0) showinfo = debug = 1;
  else if (strcmp(arg, "-M") == 0) default_find_match_limit = TRUE;
#if !defined NODFA
  else if (strcmp(arg, "-dfa") == 0) all_use_dfa = 1;
#endif
  else if (strcmp(arg, "-o") == 0 && argc > 2 &&
      ((size_offsets = get_value((pcre_uint8 *)argv[op+1], &endptr)),
        *endptr == 0))
    {
    op++;
    argc--;
    }
  else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0)
    {
    int both = arg[2] == 0;
    int temp;
    if (argc > 2 && (temp = get_value((pcre_uint8 *)argv[op+1], &endptr),
                     *endptr == 0))
      {
      timeitm = temp;
      op++;
      argc--;
      }
    else timeitm = LOOPREPEAT;
    if (both) timeit = timeitm;
    }
  else if (strcmp(arg, "-S") == 0 && argc > 2 &&
      ((stack_size = get_value((pcre_uint8 *)argv[op+1], &endptr)),
        *endptr == 0))
    {
/* ZA - z/OS behaves like windows in that case*/
#if defined(_WIN32) || defined(WIN32) || defined(__minix) || defined(NATIVE_ZOS)
    printf("PCRE: -S not supported on this OS\n");
    exit(1);
#else
    int rc;
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = stack_size * 1024 * 1024;
    rc = setrlimit(RLIMIT_STACK, &rlim);
    if (rc != 0)
      {
    printf("PCRE: setrlimit() failed with error %d\n", rc);
    exit(1);
      }
    op++;
    argc--;
#endif
    }
#if !defined NOPOSIX
  else if (strcmp(arg, "-p") == 0) posix = 1;
#endif
  else if (strcmp(arg, "-C") == 0)
    {
    int rc;
    unsigned long int lrc;

    if (argc > 2)
      {
      if (strcmp(argv[op + 1], "linksize") == 0)
        {
        (void)PCRE_CONFIG(PCRE_CONFIG_LINK_SIZE, &rc);
        printf("%d\n", rc);
        yield = rc;
        goto EXIT;
        }
      if (strcmp(argv[op + 1], "pcre8") == 0)
        {
#ifdef SUPPORT_PCRE8
        printf("1\n");
        yield = 1;
#else
        printf("0\n");
        yield = 0;
#endif
        goto EXIT;
        }
      if (strcmp(argv[op + 1], "pcre16") == 0)
        {
#ifdef SUPPORT_PCRE16
        printf("1\n");
        yield = 1;
#else
        printf("0\n");
        yield = 0;
#endif
        goto EXIT;
        }
      if (strcmp(argv[op + 1], "utf") == 0)
        {
#ifdef SUPPORT_PCRE8
        (void)CONFIG8(PCRE_CONFIG_UTF8, &rc);
        printf("%d\n", rc);
        yield = rc;
#else
        (void)pcre16_config(PCRE_CONFIG_UTF16, &rc);
        printf("%d\n", rc);
        yield = rc;
#endif
        goto EXIT;
        }
      if (strcmp(argv[op + 1], "ucp") == 0)
        {
        (void)PCRE_CONFIG(PCRE_CONFIG_UNICODE_PROPERTIES, &rc);
        printf("%d\n", rc);
        yield = rc;
        goto EXIT;
        }
      if (strcmp(argv[op + 1], "jit") == 0)
        {
        (void)PCRE_CONFIG(PCRE_CONFIG_JIT, &rc);
        printf("%d\n", rc);
        yield = rc;
        goto EXIT;
        }
      if (strcmp(argv[op + 1], "newline") == 0)
        {
        (void)PCRE_CONFIG(PCRE_CONFIG_NEWLINE, &rc);
        /* Note that these values are always the ASCII values, even
        in EBCDIC environments. CR is 13 and NL is 10. */
        printf("%s\n", (rc == 13)? "CR" :
          (rc == 10)? "LF" : (rc == (13<<8 | 10))? "CRLF" :
          (rc == -2)? "ANYCRLF" :
          (rc == -1)? "ANY" : "???");
        goto EXIT;
        }
      printf("Unknown -C option: %s\n", argv[op + 1]);
      goto EXIT;
      }

    printf("PCRE version %s\n", version);
    printf("Compiled with\n");

/* At least one of SUPPORT_PCRE8 and SUPPORT_PCRE16 will be set. If both
are set, either both UTFs are supported or both are not supported. */

#if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16
    printf("  8-bit and 16-bit support\n");
    (void)CONFIG8(PCRE_CONFIG_UTF8, &rc);
    if (rc)
      printf("  UTF-8 and UTF-16 support\n");
    else
      printf("  No UTF-8 or UTF-16 support\n");
#elif defined SUPPORT_PCRE8
    printf("  8-bit support only\n");
    (void)CONFIG8(PCRE_CONFIG_UTF8, &rc);
    printf("  %sUTF-8 support\n", rc? "" : "No ");
#else
    printf("  16-bit support only\n");
    (void)pcre16_config(PCRE_CONFIG_UTF16, &rc);
    printf("  %sUTF-16 support\n", rc? "" : "No ");
#endif

    (void)PCRE_CONFIG(PCRE_CONFIG_UNICODE_PROPERTIES, &rc);
    printf("  %sUnicode properties support\n", rc? "" : "No ");
    (void)PCRE_CONFIG(PCRE_CONFIG_JIT, &rc);
    if (rc)
      {
      const char *arch;
      (void)PCRE_CONFIG(PCRE_CONFIG_JITTARGET, (void *)(&arch));
      printf("  Just-in-time compiler support: %s\n", arch);
      }
    else
      printf("  No just-in-time compiler support\n");
    (void)PCRE_CONFIG(PCRE_CONFIG_NEWLINE, &rc);
    /* Note that these values are always the ASCII values, even
    in EBCDIC environments. CR is 13 and NL is 10. */
    printf("  Newline sequence is %s\n", (rc == 13)? "CR" :
      (rc == 10)? "LF" : (rc == (13<<8 | 10))? "CRLF" :
      (rc == -2)? "ANYCRLF" :
      (rc == -1)? "ANY" : "???");
    (void)PCRE_CONFIG(PCRE_CONFIG_BSR, &rc);
    printf("  \\R matches %s\n", rc? "CR, LF, or CRLF only" :
                                     "all Unicode newlines");
    (void)PCRE_CONFIG(PCRE_CONFIG_LINK_SIZE, &rc);
    printf("  Internal link size = %d\n", rc);
    (void)PCRE_CONFIG(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc);
    printf("  POSIX malloc threshold = %d\n", rc);
    (void)PCRE_CONFIG(PCRE_CONFIG_MATCH_LIMIT, &lrc);
    printf("  Default match limit = %ld\n", lrc);
    (void)PCRE_CONFIG(PCRE_CONFIG_MATCH_LIMIT_RECURSION, &lrc);
    printf("  Default recursion depth limit = %ld\n", lrc);
    (void)PCRE_CONFIG(PCRE_CONFIG_STACKRECURSE, &rc);
    printf("  Match recursion uses %s", rc? "stack" : "heap");
    if (showstore)
      {
      PCRE_EXEC(stack_size, NULL, NULL, NULL, -999, -999, 0, NULL, 0);
      printf(": %sframe size = %d bytes", rc? "approximate " : "", -stack_size);
      }
    printf("\n");
    goto EXIT;
    }
  else if (strcmp(arg, "-help") == 0 ||
           strcmp(arg, "--help") == 0)
    {
    usage();
    goto EXIT;
    }
  else
    {
    BAD_ARG:
    printf("** Unknown or malformed option %s\n", arg);
    usage();
    yield = 1;
    goto EXIT;
    }
  op++;
  argc--;
  }

/* Get the store for the offsets vector, and remember what it was */

size_offsets_max = size_offsets;
offsets = (int *)malloc(size_offsets_max * sizeof(int));
if (offsets == NULL)
  {
  printf("** Failed to get %d bytes of memory for offsets vector\n",
    (int)(size_offsets_max * sizeof(int)));
  yield = 1;
  goto EXIT;
  }

/* Sort out the input and output files */

if (argc > 1)
  {
  infile = fopen(argv[op], INPUT_MODE);
  if (infile == NULL)
    {
    printf("** Failed to open %s\n", argv[op]);
    yield = 1;
    goto EXIT;
    }
  }

if (argc > 2)
  {
  outfile = fopen(argv[op+1], OUTPUT_MODE);
  if (outfile == NULL)
    {
    printf("** Failed to open %s\n", argv[op+1]);
    yield = 1;
    goto EXIT;
    }
  }

/* Set alternative malloc function */

#ifdef SUPPORT_PCRE8
pcre_malloc = new_malloc;
pcre_free = new_free;
pcre_stack_malloc = stack_malloc;
pcre_stack_free = stack_free;
#endif

#ifdef SUPPORT_PCRE16
pcre16_malloc = new_malloc;
pcre16_free = new_free;
pcre16_stack_malloc = stack_malloc;
pcre16_stack_free = stack_free;
#endif

/* Heading line unless quiet, then prompt for first regex if stdin */

if (!quiet) fprintf(outfile, "PCRE version %s\n\n", version);

/* Main loop */

while (!done)
  {
  pcre *re = NULL;
  pcre_extra *extra = NULL;

#if !defined NOPOSIX  /* There are still compilers that require no indent */
  regex_t preg;
  int do_posix = 0;
#endif

  const char *error;
  pcre_uint8 *markptr;
  pcre_uint8 *p, *pp, *ppp;
  pcre_uint8 *to_file = NULL;
  const pcre_uint8 *tables = NULL;
  unsigned long int get_options;
  unsigned long int true_size, true_study_size = 0;
  size_t size, regex_gotten_store;
  int do_allcaps = 0;
  int do_mark = 0;
  int do_study = 0;
  int no_force_study = 0;
  int do_debug = debug;
  int do_G = 0;
  int do_g = 0;
  int do_showinfo = showinfo;
  int do_showrest = 0;
  int do_showcaprest = 0;
  int do_flip = 0;
  int erroroffset, len, delimiter, poffset;

#if !defined NODFA
  int dfa_matched = 0;
#endif

  use_utf = 0;
  debug_lengths = 1;

  if (extend_inputline(infile, buffer, "  re> ") == NULL) break;
  if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
  fflush(outfile);

  p = buffer;
  while (isspace(*p)) p++;
  if (*p == 0) continue;

  /* See if the pattern is to be loaded pre-compiled from a file. */

  if (*p == '<' && strchr((char *)(p+1), '<') == NULL)
    {
    pcre_uint32 magic;
    pcre_uint8 sbuf[8];
    FILE *f;

    p++;
    if (*p == '!')
      {
      do_debug = TRUE;
      do_showinfo = TRUE;
      p++;
      }

    pp = p + (int)strlen((char *)p);
    while (isspace(pp[-1])) pp--;
    *pp = 0;

    f = fopen((char *)p, "r");
    if (f == NULL)
      {
      fprintf(outfile, "Failed to open %s: %s\n", p, strerror(errno));
      continue;
      }

    first_gotten_store = 0;
    if (fread(sbuf, 1, 8, f) != 8) goto FAIL_READ;

    true_size =
      (sbuf[0] << 24) | (sbuf[1] << 16) | (sbuf[2] << 8) | sbuf[3];
    true_study_size =
      (sbuf[4] << 24) | (sbuf[5] << 16) | (sbuf[6] << 8) | sbuf[7];

    re = (pcre *)new_malloc(true_size);
    regex_gotten_store = first_gotten_store;

    if (fread(re, 1, true_size, f) != true_size) goto FAIL_READ;

    magic = ((REAL_PCRE *)re)->magic_number;
    if (magic != MAGIC_NUMBER)
      {
      if (swap_uint32(magic) == MAGIC_NUMBER)
        {
        do_flip = 1;
        }
      else
        {
        fprintf(outfile, "Data in %s is not a compiled PCRE regex\n", p);
        fclose(f);
        continue;
        }
      }

    /* We hide the byte-invert info for little and big endian tests. */
    fprintf(outfile, "Compiled pattern%s loaded from %s\n",
      do_flip && (p[-1] == '<') ? " (byte-inverted)" : "", p);

    /* Now see if there is any following study data. */

    if (true_study_size != 0)
      {
      pcre_study_data *psd;

      extra = (pcre_extra *)new_malloc(sizeof(pcre_extra) + true_study_size);
      extra->flags = PCRE_EXTRA_STUDY_DATA;

      psd = (pcre_study_data *)(((char *)extra) + sizeof(pcre_extra));
      extra->study_data = psd;

      if (fread(psd, 1, true_study_size, f) != true_study_size)
        {
        FAIL_READ:
        fprintf(outfile, "Failed to read data from %s\n", p);
        if (extra != NULL)
          {
          PCRE_FREE_STUDY(extra);
          }
        if (re != NULL) new_free(re);
        fclose(f);
        continue;
        }
      fprintf(outfile, "Study data loaded from %s\n", p);
      do_study = 1;     /* To get the data output if requested */
      }
    else fprintf(outfile, "No study data\n");

    /* Flip the necessary bytes. */
    if (do_flip)
      {
      int rc;
      PCRE_PATTERN_TO_HOST_BYTE_ORDER(rc, re, extra, NULL);
      if (rc == PCRE_ERROR_BADMODE)
        {
        /* Simulate the result of the function call below. */
        fprintf(outfile, "Error %d from pcre%s_fullinfo(%d)\n", rc,
          use_pcre16? "16" : "", PCRE_INFO_OPTIONS);
        fprintf(outfile, "Running in %s-bit mode but pattern was compiled in "
          "%s-bit mode\n", use_pcre16? "16":"8", use_pcre16? "8":"16");
        continue;
        }
      }

    /* Need to know if UTF-8 for printing data strings. */

    if (new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options) < 0) continue;
    use_utf = (get_options & PCRE_UTF8) != 0;

    fclose(f);
    goto SHOW_INFO;
    }

  /* In-line pattern (the usual case). Get the delimiter and seek the end of
  the pattern; if it isn't complete, read more. */

  delimiter = *p++;

  if (isalnum(delimiter) || delimiter == '\\')
    {
    fprintf(outfile, "** Delimiter must not be alphanumeric or \\\n");
    goto SKIP_DATA;
    }

  pp = p;
  poffset = (int)(p - buffer);

  for(;;)
    {
    while (*pp != 0)
      {
      if (*pp == '\\' && pp[1] != 0) pp++;
        else if (*pp == delimiter) break;
      pp++;
      }
    if (*pp != 0) break;
    if ((pp = extend_inputline(infile, pp, "    > ")) == NULL)
      {
      fprintf(outfile, "** Unexpected EOF\n");
      done = 1;
      goto CONTINUE;
      }
    if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
    }

  /* The buffer may have moved while being extended; reset the start of data
  pointer to the correct relative point in the buffer. */

  p = buffer + poffset;

  /* If the first character after the delimiter is backslash, make
  the pattern end with backslash. This is purely to provide a way
  of testing for the error message when a pattern ends with backslash. */

  if (pp[1] == '\\') *pp++ = '\\';

  /* Terminate the pattern at the delimiter, and save a copy of the pattern
  for callouts. */

  *pp++ = 0;
  strcpy((char *)pbuffer, (char *)p);

  /* Look for options after final delimiter */

  options = 0;
  study_options = 0;
  log_store = showstore;  /* default from command line */

  while (*pp != 0)
    {
    switch (*pp++)
      {
      case 'f': options |= PCRE_FIRSTLINE; break;
      case 'g': do_g = 1; break;
      case 'i': options |= PCRE_CASELESS; break;
      case 'm': options |= PCRE_MULTILINE; break;
      case 's': options |= PCRE_DOTALL; break;
      case 'x': options |= PCRE_EXTENDED; break;

      case '+':
      if (do_showrest) do_showcaprest = 1; else do_showrest = 1;
      break;

      case '=': do_allcaps = 1; break;
      case 'A': options |= PCRE_ANCHORED; break;
      case 'B': do_debug = 1; break;
      case 'C': options |= PCRE_AUTO_CALLOUT; break;
      case 'D': do_debug = do_showinfo = 1; break;
      case 'E': options |= PCRE_DOLLAR_ENDONLY; break;
      case 'F': do_flip = 1; break;
      case 'G': do_G = 1; break;
      case 'I': do_showinfo = 1; break;
      case 'J': options |= PCRE_DUPNAMES; break;
      case 'K': do_mark = 1; break;
      case 'M': log_store = 1; break;
      case 'N': options |= PCRE_NO_AUTO_CAPTURE; break;

#if !defined NOPOSIX
      case 'P': do_posix = 1; break;
#endif

      case 'S':
      if (do_study == 0)
        {
        do_study = 1;
        if (*pp == '+')
          {
          if (*(++pp) == '+')
            {
            verify_jit = TRUE;
            pp++;
            }
          if (*pp >= '1' && *pp <= '7')
            study_options |= jit_study_bits[*pp++ - '1'];
          else
            study_options |= jit_study_bits[6];
          }
        }
      else
        {
        do_study = 0;
        no_force_study = 1;
        }
      break;

      case 'U': options |= PCRE_UNGREEDY; break;
      case 'W': options |= PCRE_UCP; break;
      case 'X': options |= PCRE_EXTRA; break;
      case 'Y': options |= PCRE_NO_START_OPTIMISE; break;
      case 'Z': debug_lengths = 0; break;
      case '8': options |= PCRE_UTF8; use_utf = 1; break;
      case '?': options |= PCRE_NO_UTF8_CHECK; break;

      case 'T':
      switch (*pp++)
        {
        case '0': tables = tables0; break;
        case '1': tables = tables1; break;

        case '\r':
        case '\n':
        case ' ':
        case 0:
        fprintf(outfile, "** Missing table number after /T\n");
        goto SKIP_DATA;

        default:
        fprintf(outfile, "** Bad table number \"%c\" after /T\n", pp[-1]);
        goto SKIP_DATA;
        }
      break;

      case 'L':
      ppp = pp;
      /* The '\r' test here is so that it works on Windows. */
      /* The '0' test is just in case this is an unterminated line. */
      while (*ppp != 0 && *ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++;
      *ppp = 0;
      if (setlocale(LC_CTYPE, (const char *)pp) == NULL)
        {
        fprintf(outfile, "** Failed to set locale \"%s\"\n", pp);
        goto SKIP_DATA;
        }
      locale_set = 1;
      tables = PCRE_MAKETABLES;
      pp = ppp;
      break;

      case '>':
      to_file = pp;
      while (*pp != 0) pp++;
      while (isspace(pp[-1])) pp--;
      *pp = 0;
      break;

      case '<':
        {
        if (strncmpic(pp, (pcre_uint8 *)"JS>", 3) == 0)
          {
          options |= PCRE_JAVASCRIPT_COMPAT;
          pp += 3;
          }
        else
          {
          int x = check_newline(pp, outfile);
          if (x == 0) goto SKIP_DATA;
          options |= x;
          while (*pp++ != '>');
          }
        }
      break;

      case '\r':                      /* So that it works in Windows */
      case '\n':
      case ' ':
      break;

      default:
      fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);
      goto SKIP_DATA;
      }
    }

  /* Handle compiling via the POSIX interface, which doesn't support the
  timing, showing, or debugging options, nor the ability to pass over
  local character tables. Neither does it have 16-bit support. */

#if !defined NOPOSIX
  if (posix || do_posix)
    {
    int rc;
    int cflags = 0;

    if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;
    if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;
    if ((options & PCRE_DOTALL) != 0) cflags |= REG_DOTALL;
    if ((options & PCRE_NO_AUTO_CAPTURE) != 0) cflags |= REG_NOSUB;
    if ((options & PCRE_UTF8) != 0) cflags |= REG_UTF8;
    if ((options & PCRE_UCP) != 0) cflags |= REG_UCP;
    if ((options & PCRE_UNGREEDY) != 0) cflags |= REG_UNGREEDY;

    first_gotten_store = 0;
    rc = regcomp(&preg, (char *)p, cflags);

    /* Compilation failed; go back for another re, skipping to blank line
    if non-interactive. */

    if (rc != 0)
      {
      (void)regerror(rc, &preg, (char *)buffer, buffer_size);
      fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer);
      goto SKIP_DATA;
      }
    }

  /* Handle compiling via the native interface */

  else
#endif  /* !defined NOPOSIX */

    {
    /* In 16-bit mode, convert the input. */

#ifdef SUPPORT_PCRE16
    if (use_pcre16)
      {
      switch(to16(FALSE, p, options & PCRE_UTF8, (int)strlen((char *)p)))
        {
        case -1:
        fprintf(outfile, "**Failed: invalid UTF-8 string cannot be "
          "converted to UTF-16\n");
        goto SKIP_DATA;

        case -2:
        fprintf(outfile, "**Failed: character value greater than 0x10ffff "
          "cannot be converted to UTF-16\n");
        goto SKIP_DATA;

        case -3: /* "Impossible error" when to16 is called arg1 FALSE */
        fprintf(outfile, "**Failed: character value greater than 0xffff "
          "cannot be converted to 16-bit in non-UTF mode\n");
        goto SKIP_DATA;

        default:
        break;
        }
      p = (pcre_uint8 *)buffer16;
      }
#endif

    /* Compile many times when timing */

    if (timeit > 0)
      {
      register int i;
      clock_t time_taken;
      clock_t start_time = clock();
      for (i = 0; i < timeit; i++)
        {
        PCRE_COMPILE(re, p, options, &error, &erroroffset, tables);
        if (re != NULL) free(re);
        }
      time_taken = clock() - start_time;
      fprintf(outfile, "Compile time %.4f milliseconds\n",
        (((double)time_taken * 1000.0) / (double)timeit) /
          (double)CLOCKS_PER_SEC);
      }

    first_gotten_store = 0;
    PCRE_COMPILE(re, p, options, &error, &erroroffset, tables);

    /* Compilation failed; go back for another re, skipping to blank line
    if non-interactive. */

    if (re == NULL)
      {
      fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset);
      SKIP_DATA:
      if (infile != stdin)
        {
        for (;;)
          {
          if (extend_inputline(infile, buffer, NULL) == NULL)
            {
            done = 1;
            goto CONTINUE;
            }
          len = (int)strlen((char *)buffer);
          while (len > 0 && isspace(buffer[len-1])) len--;
          if (len == 0) break;
          }
        fprintf(outfile, "\n");
        }
      goto CONTINUE;
      }

    /* Compilation succeeded. It is now possible to set the UTF-8 option from
    within the regex; check for this so that we know how to process the data
    lines. */

    if (new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options) < 0)
      goto SKIP_DATA;
    if ((get_options & PCRE_UTF8) != 0) use_utf = 1;

    /* Extract the size for possible writing before possibly flipping it,
    and remember the store that was got. */

    true_size = ((REAL_PCRE *)re)->size;
    regex_gotten_store = first_gotten_store;

    /* Output code size information if requested */

    if (log_store)
      fprintf(outfile, "Memory allocation (code space): %d\n",
        (int)(first_gotten_store -
              sizeof(REAL_PCRE) -
              ((REAL_PCRE *)re)->name_count * ((REAL_PCRE *)re)->name_entry_size));

    /* If -s or /S was present, study the regex to generate additional info to
    help with the matching, unless the pattern has the SS option, which
    suppresses the effect of /S (used for a few test patterns where studying is
    never sensible). */

    if (do_study || (force_study >= 0 && !no_force_study))
      {
      if (timeit > 0)
        {
        register int i;
        clock_t time_taken;
        clock_t start_time = clock();
        for (i = 0; i < timeit; i++)
          {
          PCRE_STUDY(extra, re, study_options | force_study_options, &error);
          }
        time_taken = clock() - start_time;
        if (extra != NULL)
          {
          PCRE_FREE_STUDY(extra);
          }
        fprintf(outfile, "  Study time %.4f milliseconds\n",
          (((double)time_taken * 1000.0) / (double)timeit) /
            (double)CLOCKS_PER_SEC);
        }
      PCRE_STUDY(extra, re, study_options | force_study_options, &error);
      if (error != NULL)
        fprintf(outfile, "Failed to study: %s\n", error);
      else if (extra != NULL)
        {
        true_study_size = ((pcre_study_data *)(extra->study_data))->size;
        if (log_store)
          {
          size_t jitsize;
          if (new_info(re, extra, PCRE_INFO_JITSIZE, &jitsize) == 0 &&
              jitsize != 0)
            fprintf(outfile, "Memory allocation (JIT code): %d\n", (int)jitsize);
          }
        }
      }

    /* If /K was present, we set up for handling MARK data. */

    if (do_mark)
      {
      if (extra == NULL)
        {
        extra = (pcre_extra *)malloc(sizeof(pcre_extra));
        extra->flags = 0;
        }
      extra->mark = &markptr;
      extra->flags |= PCRE_EXTRA_MARK;
      }

    /* Extract and display information from the compiled data if required. */

    SHOW_INFO:

    if (do_debug)
      {
      fprintf(outfile, "------------------------------------------------------------------\n");
      PCRE_PRINTINT(re, outfile, debug_lengths);
      }

    /* We already have the options in get_options (see above) */

    if (do_showinfo)
      {
      unsigned long int all_options;
      int count, backrefmax, first_char, need_char, okpartial, jchanged,
        hascrorlf, maxlookbehind;
      int nameentrysize, namecount;
      const pcre_uint8 *nametable;

      if (new_info(re, NULL, PCRE_INFO_SIZE, &size) +
          new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count) +
          new_info(re, NULL, PCRE_INFO_BACKREFMAX, &backrefmax) +
          new_info(re, NULL, PCRE_INFO_FIRSTBYTE, &first_char) +
          new_info(re, NULL, PCRE_INFO_LASTLITERAL, &need_char) +
          new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize) +
          new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount) +
          new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable) +
          new_info(re, NULL, PCRE_INFO_OKPARTIAL, &okpartial) +
          new_info(re, NULL, PCRE_INFO_JCHANGED, &jchanged) +
          new_info(re, NULL, PCRE_INFO_HASCRORLF, &hascrorlf) +
          new_info(re, NULL, PCRE_INFO_MAXLOOKBEHIND, &maxlookbehind)
          != 0)
        goto SKIP_DATA;

      if (size != regex_gotten_store) fprintf(outfile,
        "Size disagreement: FULLINF8=%d call to malloc for %d\n",
        (int)size, (int)regex_gotten_store);

      fprintf(outfile, "Capturing subpattern count = %d\n", count);
      if (backrefmax > 0)
        fprintf(outfile, "Max back reference = %d\n", backrefmax);

      if (namecount > 0)
        {
        fprintf(outfile, "Named capturing subpatterns:\n");
        while (namecount-- > 0)
          {
#if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16
          int imm2_size = use_pcre16 ? 1 : 2;
#else
          int imm2_size = IMM2_SIZE;
#endif
          int length = (int)STRLEN(nametable + imm2_size);
          fprintf(outfile, "  ");
          PCHARSV(nametable, imm2_size, length, outfile);
          while (length++ < nameentrysize - imm2_size) putc(' ', outfile);
#if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16
          fprintf(outfile, "%3d\n", use_pcre16?
             (int)(((PCRE_SPTR16)nametable)[0])
            :((int)nametable[0] << 8) | (int)nametable[1]);
          nametable += nameentrysize * (use_pcre16 ? 2 : 1);
#else
          fprintf(outfile, "%3d\n", GET2(nametable, 0));
#ifdef SUPPORT_PCRE8
          nametable += nameentrysize;
#else
          nametable += nameentrysize * 2;
#endif
#endif
          }
        }

      if (!okpartial) fprintf(outfile, "Partial matching not supported\n");
      if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n");

      all_options = ((REAL_PCRE *)re)->options;
      if (do_flip) all_options = swap_uint32(all_options);

      if (get_options == 0) fprintf(outfile, "No options\n");
        else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
          ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",
          ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",
          ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",
          ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",
          ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "",
          ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",
          ((get_options & PCRE_BSR_ANYCRLF) != 0)? " bsr_anycrlf" : "",
          ((get_options & PCRE_BSR_UNICODE) != 0)? " bsr_unicode" : "",
          ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
          ((get_options & PCRE_EXTRA) != 0)? " extra" : "",
          ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",
          ((get_options & PCRE_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",
          ((get_options & PCRE_UTF8) != 0)? " utf" : "",
          ((get_options & PCRE_UCP) != 0)? " ucp" : "",
          ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf_check" : "",
          ((get_options & PCRE_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "",
          ((get_options & PCRE_DUPNAMES) != 0)? " dupnames" : "");

      if (jchanged) fprintf(outfile, "Duplicate name status changes\n");

      switch (get_options & PCRE_NEWLINE_BITS)
        {
        case PCRE_NEWLINE_CR:
        fprintf(outfile, "Forced newline sequence: CR\n");
        break;

        case PCRE_NEWLINE_LF:
        fprintf(outfile, "Forced newline sequence: LF\n");
        break;

        case PCRE_NEWLINE_CRLF:
        fprintf(outfile, "Forced newline sequence: CRLF\n");
        break;

        case PCRE_NEWLINE_ANYCRLF:
        fprintf(outfile, "Forced newline sequence: ANYCRLF\n");
        break;

        case PCRE_NEWLINE_ANY:
        fprintf(outfile, "Forced newline sequence: ANY\n");
        break;

        default:
        break;
        }

      if (first_char == -1)
        {
        fprintf(outfile, "First char at start or follows newline\n");
        }
      else if (first_char < 0)
        {
        fprintf(outfile, "No first char\n");
        }
      else
        {
        const char *caseless =
          ((((REAL_PCRE *)re)->flags & PCRE_FCH_CASELESS) == 0)?
          "" : " (caseless)";

        if (PRINTOK(first_char))
          fprintf(outfile, "First char = \'%c\'%s\n", first_char, caseless);
        else
          {
          fprintf(outfile, "First char = ");
          pchar(first_char, outfile);
          fprintf(outfile, "%s\n", caseless);
          }
        }

      if (need_char < 0)
        {
        fprintf(outfile, "No need char\n");
        }
      else
        {
        const char *caseless =
          ((((REAL_PCRE *)re)->flags & PCRE_RCH_CASELESS) == 0)?
          "" : " (caseless)";

        if (PRINTOK(need_char))
          fprintf(outfile, "Need char = \'%c\'%s\n", need_char, caseless);
        else
          {
          fprintf(outfile, "Need char = ");
          pchar(need_char, outfile);
          fprintf(outfile, "%s\n", caseless);
          }
        }

      if (maxlookbehind > 0)
        fprintf(outfile, "Max lookbehind = %d\n", maxlookbehind);

      /* Don't output study size; at present it is in any case a fixed
      value, but it varies, depending on the computer architecture, and
      so messes up the test suite. (And with the /F option, it might be
      flipped.) If study was forced by an external -s, don't show this
      information unless -i or -d was also present. This means that, except
      when auto-callouts are involved, the output from runs with and without
      -s should be identical. */

      if (do_study || (force_study >= 0 && showinfo && !no_force_study))
        {
        if (extra == NULL)
          fprintf(outfile, "Study returned NULL\n");
        else
          {
          pcre_uint8 *start_bits = NULL;
          int minlength;

          if (new_info(re, extra, PCRE_INFO_MINLENGTH, &minlength) == 0)
            fprintf(outfile, "Subject length lower bound = %d\n", minlength);

          if (new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits) == 0)
            {
            if (start_bits == NULL)
              fprintf(outfile, "No set of starting bytes\n");
            else
              {
              int i;
              int c = 24;
              fprintf(outfile, "Starting byte set: ");
              for (i = 0; i < 256; i++)
                {
                if ((start_bits[i/8] & (1<<(i&7))) != 0)
                  {
                  if (c > 75)
                    {
                    fprintf(outfile, "\n  ");
                    c = 2;
                    }
                  if (PRINTOK(i) && i != ' ')
                    {
                    fprintf(outfile, "%c ", i);
                    c += 2;
                    }
                  else
                    {
                    fprintf(outfile, "\\x%02x ", i);
                    c += 5;
                    }
                  }
                }
              fprintf(outfile, "\n");
              }
            }
          }

        /* Show this only if the JIT was set by /S, not by -s. */

        if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0)
          {
          int jit;
          if (new_info(re, extra, PCRE_INFO_JIT, &jit) == 0)
            {
            if (jit)
              fprintf(outfile, "JIT study was successful\n");
            else
#ifdef SUPPORT_JIT
              fprintf(outfile, "JIT study was not successful\n");
#else
              fprintf(outfile, "JIT support is not available in this version of PCRE\n");
#endif
            }
          }
        }
      }

    /* If the '>' option was present, we write out the regex to a file, and
    that is all. The first 8 bytes of the file are the regex length and then
    the study length, in big-endian order. */

    if (to_file != NULL)
      {
      FILE *f = fopen((char *)to_file, "w");
      if (f == NULL)
        {
        fprintf(outfile, "Unable to open %s: %s\n", to_file, strerror(errno));
        }
      else
        {
        pcre_uint8 sbuf[8];

        if (do_flip) regexflip(re, extra);
        sbuf[0] = (pcre_uint8)((true_size >> 24) & 255);
        sbuf[1] = (pcre_uint8)((true_size >> 16) & 255);
        sbuf[2] = (pcre_uint8)((true_size >>  8) & 255);
        sbuf[3] = (pcre_uint8)((true_size) & 255);
        sbuf[4] = (pcre_uint8)((true_study_size >> 24) & 255);
        sbuf[5] = (pcre_uint8)((true_study_size >> 16) & 255);
        sbuf[6] = (pcre_uint8)((true_study_size >>  8) & 255);
        sbuf[7] = (pcre_uint8)((true_study_size) & 255);

        if (fwrite(sbuf, 1, 8, f) < 8 ||
            fwrite(re, 1, true_size, f) < true_size)
          {
          fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno));
          }
        else
          {
          fprintf(outfile, "Compiled pattern written to %s\n", to_file);

          /* If there is study data, write it. */

          if (extra != NULL)
            {
            if (fwrite(extra->study_data, 1, true_study_size, f) <
                true_study_size)
              {
              fprintf(outfile, "Write error on %s: %s\n", to_file,
                strerror(errno));
              }
            else fprintf(outfile, "Study data written to %s\n", to_file);
            }
          }
        fclose(f);
        }

      new_free(re);
      if (extra != NULL)
        {
        PCRE_FREE_STUDY(extra);
        }
      if (locale_set)
        {
        new_free((void *)tables);
        setlocale(LC_CTYPE, "C");
        locale_set = 0;
        }
      continue;  /* With next regex */
      }
    }        /* End of non-POSIX compile */

  /* Read data lines and test them */

  for (;;)
    {
    pcre_uint8 *q;
    pcre_uint8 *bptr;
    int *use_offsets = offsets;
    int use_size_offsets = size_offsets;
    int callout_data = 0;
    int callout_data_set = 0;
    int count, c;
    int copystrings = 0;
    int find_match_limit = default_find_match_limit;
    int getstrings = 0;
    int getlist = 0;
    int gmatched = 0;
    int start_offset = 0;
    int start_offset_sign = 1;
    int g_notempty = 0;
    int use_dfa = 0;

    *copynames = 0;
    *getnames = 0;

#ifdef SUPPORT_PCRE16
    cn16ptr = copynames;
    gn16ptr = getnames;
#endif
#ifdef SUPPORT_PCRE8
    cn8ptr = copynames8;
    gn8ptr = getnames8;
#endif

    SET_PCRE_CALLOUT(callout);
    first_callout = 1;
    last_callout_mark = NULL;
    callout_extra = 0;
    callout_count = 0;
    callout_fail_count = 999999;
    callout_fail_id = -1;
    show_malloc = 0;
    options = 0;

    if (extra != NULL) extra->flags &=
      ~(PCRE_EXTRA_MATCH_LIMIT|PCRE_EXTRA_MATCH_LIMIT_RECURSION);

    len = 0;
    for (;;)
      {
      if (extend_inputline(infile, buffer + len, "data> ") == NULL)
        {
        if (len > 0)    /* Reached EOF without hitting a newline */
          {
          fprintf(outfile, "\n");
          break;
          }
        done = 1;
        goto CONTINUE;
        }
      if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
      len = (int)strlen((char *)buffer);
      if (buffer[len-1] == '\n') break;
      }

    while (len > 0 && isspace(buffer[len-1])) len--;
    buffer[len] = 0;
    if (len == 0) break;

    p = buffer;
    while (isspace(*p)) p++;

    bptr = q = dbuffer;
    while ((c = *p++) != 0)
      {
      int i = 0;
      int n = 0;

      /* In UTF mode, input can be UTF-8, so just copy all non-backslash bytes.
      In non-UTF mode, allow the value of the byte to fall through to later,
      where values greater than 127 are turned into UTF-8 when running in
      16-bit mode. */

      if (c != '\\')
        {
        if (use_utf)
          {
          *q++ = c;
          continue;
          }
        }

      /* Handle backslash escapes */

      else switch ((c = *p++))
        {
        case 'a': c =    7; break;
        case 'b': c = '\b'; break;
        case 'e': c =   27; break;
        case 'f': c = '\f'; break;
        case 'n': c = '\n'; break;
        case 'r': c = '\r'; break;
        case 't': c = '\t'; break;
        case 'v': c = '\v'; break;

        case '0': case '1': case '2': case '3':
        case '4': case '5': case '6': case '7':
        c -= '0';
        while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')
          c = c * 8 + *p++ - '0';
        break;

        case 'x':
        if (*p == '{')
          {
          pcre_uint8 *pt = p;
          c = 0;

          /* We used to have "while (isxdigit(*(++pt)))" here, but it fails
          when isxdigit() is a macro that refers to its argument more than
          once. This is banned by the C Standard, but apparently happens in at
          least one MacOS environment. */

          for (pt++; isxdigit(*pt); pt++)
            {
            if (++i == 9)
              fprintf(outfile, "** Too many hex digits in \\x{...} item; "
                               "using only the first eight.\n");
            else c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'a' - 10);
            }
          if (*pt == '}')
            {
            p = pt + 1;
            break;
            }
          /* Not correct form for \x{...}; fall through */
          }

        /* \x without {} always defines just one byte in 8-bit mode. This
        allows UTF-8 characters to be constructed byte by byte, and also allows
        invalid UTF-8 sequences to be made. Just copy the byte in UTF mode.
        Otherwise, pass it down to later code so that it can be turned into
        UTF-8 when running in 16-bit mode. */

        c = 0;
        while (i++ < 2 && isxdigit(*p))
          {
          c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'a' - 10);
          p++;
          }
        if (use_utf)
          {
          *q++ = c;
          continue;
          }
        break;

        case 0:   /* \ followed by EOF allows for an empty line */
        p--;
        continue;

        case '>':
        if (*p == '-')
          {
          start_offset_sign = -1;
          p++;
          }
        while(isdigit(*p)) start_offset = start_offset * 10 + *p++ - '0';
        start_offset *= start_offset_sign;
        continue;

        case 'A':  /* Option setting */
        options |= PCRE_ANCHORED;
        continue;

        case 'B':
        options |= PCRE_NOTBOL;
        continue;

        case 'C':
        if (isdigit(*p))    /* Set copy string */
          {
          while(isdigit(*p)) n = n * 10 + *p++ - '0';
          copystrings |= 1 << n;
          }
        else if (isalnum(*p))
          {
          READ_CAPTURE_NAME(p, &cn8ptr, &cn16ptr, re);
          }
        else if (*p == '+')
          {
          callout_extra = 1;
          p++;
          }
        else if (*p == '-')
          {
          SET_PCRE_CALLOUT(NULL);
          p++;
          }
        else if (*p == '!')
          {
          callout_fail_id = 0;
          p++;
          while(isdigit(*p))
            callout_fail_id = callout_fail_id * 10 + *p++ - '0';
          callout_fail_count = 0;
          if (*p == '!')
            {
            p++;
            while(isdigit(*p))
              callout_fail_count = callout_fail_count * 10 + *p++ - '0';
            }
          }
        else if (*p == '*')
          {
          int sign = 1;
          callout_data = 0;
          if (*(++p) == '-') { sign = -1; p++; }
          while(isdigit(*p))
            callout_data = callout_data * 10 + *p++ - '0';
          callout_data *= sign;
          callout_data_set = 1;
          }
        continue;

#if !defined NODFA
        case 'D':
#if !defined NOPOSIX
        if (posix || do_posix)
          printf("** Can't use dfa matching in POSIX mode: \\D ignored\n");
        else
#endif
          use_dfa = 1;
        continue;
#endif

#if !defined NODFA
        case 'F':
        options |= PCRE_DFA_SHORTEST;
        continue;
#endif

        case 'G':
        if (isdigit(*p))
          {
          while(isdigit(*p)) n = n * 10 + *p++ - '0';
          getstrings |= 1 << n;
          }
        else if (isalnum(*p))
          {
          READ_CAPTURE_NAME(p, &gn8ptr, &gn16ptr, re);
          }
        continue;

        case 'J':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        if (extra != NULL
            && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0
            && extra->executable_jit != NULL)
          {
          if (jit_stack != NULL) { PCRE_JIT_STACK_FREE(jit_stack); }
          jit_stack = PCRE_JIT_STACK_ALLOC(1, n * 1024);
          PCRE_ASSIGN_JIT_STACK(extra, jit_callback, jit_stack);
          }
        continue;

        case 'L':
        getlist = 1;
        continue;

        case 'M':
        find_match_limit = 1;
        continue;

        case 'N':
        if ((options & PCRE_NOTEMPTY) != 0)
          options = (options & ~PCRE_NOTEMPTY) | PCRE_NOTEMPTY_ATSTART;
        else
          options |= PCRE_NOTEMPTY;
        continue;

        case 'O':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        if (n > size_offsets_max)
          {
          size_offsets_max = n;
          free(offsets);
          use_offsets = offsets = (int *)malloc(size_offsets_max * sizeof(int));
          if (offsets == NULL)
            {
            printf("** Failed to get %d bytes of memory for offsets vector\n",
              (int)(size_offsets_max * sizeof(int)));
            yield = 1;
            goto EXIT;
            }
          }
        use_size_offsets = n;
        if (n == 0) use_offsets = NULL;   /* Ensures it can't write to it */
          else use_offsets = offsets + size_offsets_max - n;  /* To catch overruns */
        continue;

        case 'P':
        options |= ((options & PCRE_PARTIAL_SOFT) == 0)?
          PCRE_PARTIAL_SOFT : PCRE_PARTIAL_HARD;
        continue;

        case 'Q':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        if (extra == NULL)
          {
          extra = (pcre_extra *)malloc(sizeof(pcre_extra));
          extra->flags = 0;
          }
        extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
        extra->match_limit_recursion = n;
        continue;

        case 'q':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        if (extra == NULL)
          {
          extra = (pcre_extra *)malloc(sizeof(pcre_extra));
          extra->flags = 0;
          }
        extra->flags |= PCRE_EXTRA_MATCH_LIMIT;
        extra->match_limit = n;
        continue;

#if !defined NODFA
        case 'R':
        options |= PCRE_DFA_RESTART;
        continue;
#endif

        case 'S':
        show_malloc = 1;
        continue;

        case 'Y':
        options |= PCRE_NO_START_OPTIMIZE;
        continue;

        case 'Z':
        options |= PCRE_NOTEOL;
        continue;

        case '?':
        options |= PCRE_NO_UTF8_CHECK;
        continue;

        case '<':
          {
          int x = check_newline(p, outfile);
          if (x == 0) goto NEXT_DATA;
          options |= x;
          while (*p++ != '>');
          }
        continue;
        }

      /* We now have a character value in c that may be greater than 255. In
      16-bit mode, we always convert characters to UTF-8 so that values greater
      than 255 can be passed to non-UTF 16-bit strings. In 8-bit mode we
      convert to UTF-8 if we are in UTF mode. Values greater than 127 in UTF
      mode must have come from \x{...} or octal constructs because values from
      \x.. get this far only in non-UTF mode. */

#if !defined NOUTF || defined SUPPORT_PCRE16
      if (use_pcre16 || use_utf)
        {
        pcre_uint8 buff8[8];
        int ii, utn;
        utn = ord2utf8(c, buff8);
        for (ii = 0; ii < utn; ii++) *q++ = buff8[ii];
        }
      else
#endif
        {
        if (c > 255)
          {
          fprintf(outfile, "** Character \\x{%x} is greater than 255 "
            "and UTF-8 mode is not enabled.\n", c);
          fprintf(outfile, "** Truncation will probably give the wrong "
            "result.\n");
          }
        *q++ = c;
        }
      }

    /* Reached end of subject string */

    *q = 0;
    len = (int)(q - dbuffer);

    /* Move the data to the end of the buffer so that a read over the end of
    the buffer will be seen by valgrind, even if it doesn't cause a crash. If
    we are using the POSIX interface, we must include the terminating zero. */

#if !defined NOPOSIX
    if (posix || do_posix)
      {
      memmove(bptr + buffer_size - len - 1, bptr, len + 1);
      bptr += buffer_size - len - 1;
      }
    else
#endif
      {
      memmove(bptr + buffer_size - len, bptr, len);
      bptr += buffer_size - len;
      }

    if ((all_use_dfa || use_dfa) && find_match_limit)
      {
      printf("**Match limit not relevant for DFA matching: ignored\n");
      find_match_limit = 0;
      }

    /* Handle matching via the POSIX interface, which does not
    support timing or playing with the match limit or callout data. */

#if !defined NOPOSIX
    if (posix || do_posix)
      {
      int rc;
      int eflags = 0;
      regmatch_t *pmatch = NULL;
      if (use_size_offsets > 0)
        pmatch = (regmatch_t *)malloc(sizeof(regmatch_t) * use_size_offsets);
      if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL;
      if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL;
      if ((options & PCRE_NOTEMPTY) != 0) eflags |= REG_NOTEMPTY;

      rc = regexec(&preg, (const char *)bptr, use_size_offsets, pmatch, eflags);

      if (rc != 0)
        {
        (void)regerror(rc, &preg, (char *)buffer, buffer_size);
        fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);
        }
      else if ((((const pcre *)preg.re_pcre)->options & PCRE_NO_AUTO_CAPTURE)
              != 0)
        {
        fprintf(outfile, "Matched with REG_NOSUB\n");
        }
      else
        {
        size_t i;
        for (i = 0; i < (size_t)use_size_offsets; i++)
          {
          if (pmatch[i].rm_so >= 0)
            {
            fprintf(outfile, "%2d: ", (int)i);
            PCHARSV(dbuffer, pmatch[i].rm_so,
              pmatch[i].rm_eo - pmatch[i].rm_so, outfile);
            fprintf(outfile, "\n");
            if (do_showcaprest || (i == 0 && do_showrest))
              {
              fprintf(outfile, "%2d+ ", (int)i);
              PCHARSV(dbuffer, pmatch[i].rm_eo, len - pmatch[i].rm_eo,
                outfile);
              fprintf(outfile, "\n");
              }
            }
          }
        }
      free(pmatch);
      goto NEXT_DATA;
      }

#endif  /* !defined NOPOSIX */

    /* Handle matching via the native interface - repeats for /g and /G */

#ifdef SUPPORT_PCRE16
    if (use_pcre16)
      {
      len = to16(TRUE, bptr, (((REAL_PCRE *)re)->options) & PCRE_UTF8, len);
      switch(len)
        {
        case -1:
        fprintf(outfile, "**Failed: invalid UTF-8 string cannot be "
          "converted to UTF-16\n");
        goto NEXT_DATA;

        case -2:
        fprintf(outfile, "**Failed: character value greater than 0x10ffff "
          "cannot be converted to UTF-16\n");
        goto NEXT_DATA;

        case -3:
        fprintf(outfile, "**Failed: character value greater than 0xffff "
          "cannot be converted to 16-bit in non-UTF mode\n");
        goto NEXT_DATA;

        default:
        break;
        }
      bptr = (pcre_uint8 *)buffer16;
      }
#endif

    /* Ensure that there is a JIT callback if we want to verify that JIT was
    actually used. If jit_stack == NULL, no stack has yet been assigned. */

    if (verify_jit && jit_stack == NULL && extra != NULL)
       { PCRE_ASSIGN_JIT_STACK(extra, jit_callback, jit_stack); }

    for (;; gmatched++)    /* Loop for /g or /G */
      {
      markptr = NULL;
      jit_was_used = FALSE;

      if (timeitm > 0)
        {
        register int i;
        clock_t time_taken;
        clock_t start_time = clock();

#if !defined NODFA
        if (all_use_dfa || use_dfa)
          {
          if ((options & PCRE_DFA_RESTART) != 0)
            {
            fprintf(outfile, "Timing DFA restarts is not supported\n");
            break;
            }
          if (dfa_workspace == NULL)
            dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));
          for (i = 0; i < timeitm; i++)
            {
            PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset,
              (options | g_notempty), use_offsets, use_size_offsets,
              dfa_workspace, DFA_WS_DIMENSION);
            }
          }
        else
#endif

        for (i = 0; i < timeitm; i++)
          {
          PCRE_EXEC(count, re, extra, bptr, len, start_offset,
            (options | g_notempty), use_offsets, use_size_offsets);
          }
        time_taken = clock() - start_time;
        fprintf(outfile, "Execute time %.4f milliseconds\n",
          (((double)time_taken * 1000.0) / (double)timeitm) /
            (double)CLOCKS_PER_SEC);
        }

      /* If find_match_limit is set, we want to do repeated matches with
      varying limits in order to find the minimum value for the match limit and
      for the recursion limit. The match limits are relevant only to the normal
      running of PCREXEC8(), so disable the JIT optimization. This makes it
      possible to run the same set of tests with and without JIT externally
      requested. */

      if (find_match_limit)
        {
        if (extra == NULL)
          {
          extra = (pcre_extra *)malloc(sizeof(pcre_extra));
          extra->flags = 0;
          }
        else extra->flags &= ~PCRE_EXTRA_EXECUTABLE_JIT;

        (void)check_match_limit(re, extra, bptr, len, start_offset,
          options|g_notempty, use_offsets, use_size_offsets,
          PCRE_EXTRA_MATCH_LIMIT, &(extra->match_limit),
          PCRE_ERROR_MATCHLIMIT, "match()");

        count = check_match_limit(re, extra, bptr, len, start_offset,
          options|g_notempty, use_offsets, use_size_offsets,
          PCRE_EXTRA_MATCH_LIMIT_RECURSION, &(extra->match_limit_recursion),
          PCRE_ERROR_RECURSIONLIMIT, "match() recursion");
        }

      /* If callout_data is set, use the interface with additional data */

      else if (callout_data_set)
        {
        if (extra == NULL)
          {
          extra = (pcre_extra *)malloc(sizeof(pcre_extra));
          extra->flags = 0;
          }
        extra->flags |= PCRE_EXTRA_CALLOUT_DATA;
        extra->callout_data = &callout_data;
        PCRE_EXEC(count, re, extra, bptr, len, start_offset,
          options | g_notempty, use_offsets, use_size_offsets);
        extra->flags &= ~PCRE_EXTRA_CALLOUT_DATA;
        }

      /* The normal case is just to do the match once, with the default
      value of match_limit. */

#if !defined NODFA
      else if (all_use_dfa || use_dfa)
        {
        if (dfa_workspace == NULL)
          dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));
        if (dfa_matched++ == 0)
          dfa_workspace[0] = -1;  /* To catch bad restart */
        PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset,
          (options | g_notempty), use_offsets, use_size_offsets, dfa_workspace,
          DFA_WS_DIMENSION);
        if (count == 0)
          {
          fprintf(outfile, "Matched, but too many subsidiary matches\n");
          count = use_size_offsets/2;
          }
        }
#endif

      else
        {
        PCRE_EXEC(count, re, extra, bptr, len, start_offset,
          options | g_notempty, use_offsets, use_size_offsets);
        if (count == 0)
          {
          fprintf(outfile, "Matched, but too many substrings\n");
          count = use_size_offsets/3;
          }
        }

      /* Matched */

      if (count >= 0)
        {
        int i, maxcount;
        void *cnptr, *gnptr;

#if !defined NODFA
        if (all_use_dfa || use_dfa) maxcount = use_size_offsets/2; else
#endif
          maxcount = use_size_offsets/3;

        /* This is a check against a lunatic return value. */

        if (count > maxcount)
          {
          fprintf(outfile,
            "** PCRE error: returned count %d is too big for offset size %d\n",
            count, use_size_offsets);
          count = use_size_offsets/3;
          if (do_g || do_G)
            {
            fprintf(outfile, "** /%c loop abandoned\n", do_g? 'g' : 'G');
            do_g = do_G = FALSE;        /* Break g/G loop */
            }
          }

        /* do_allcaps requests showing of all captures in the pattern, to check
        unset ones at the end. */

        if (do_allcaps)
          {
          if (new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count) < 0)
            goto SKIP_DATA;
          count++;   /* Allow for full match */
          if (count * 2 > use_size_offsets) count = use_size_offsets/2;
          }

        /* Output the captured substrings */

        for (i = 0; i < count * 2; i += 2)
          {
          if (use_offsets[i] < 0)
            {
            if (use_offsets[i] != -1)
              fprintf(outfile, "ERROR: bad negative value %d for offset %d\n",
                use_offsets[i], i);
            if (use_offsets[i+1] != -1)
              fprintf(outfile, "ERROR: bad negative value %d for offset %d\n",
                use_offsets[i+1], i+1);
            fprintf(outfile, "%2d: <unset>\n", i/2);
            }
          else
            {
            fprintf(outfile, "%2d: ", i/2);
            PCHARSV(bptr, use_offsets[i],
              use_offsets[i+1] - use_offsets[i], outfile);
            if (verify_jit && jit_was_used) fprintf(outfile, " (JIT)");
            fprintf(outfile, "\n");
            if (do_showcaprest || (i == 0 && do_showrest))
              {
              fprintf(outfile, "%2d+ ", i/2);
              PCHARSV(bptr, use_offsets[i+1], len - use_offsets[i+1],
                outfile);
              fprintf(outfile, "\n");
              }
            }
          }

        if (markptr != NULL)
          {
          fprintf(outfile, "MK: ");
          PCHARSV(markptr, 0, -1, outfile);
          fprintf(outfile, "\n");
          }

        for (i = 0; i < 32; i++)
          {
          if ((copystrings & (1 << i)) != 0)
            {
            int rc;
            char copybuffer[256];
            PCRE_COPY_SUBSTRING(rc, bptr, use_offsets, count, i,
              copybuffer, sizeof(copybuffer));
            if (rc < 0)
              fprintf(outfile, "copy substring %d failed %d\n", i, rc);
            else
              {
              fprintf(outfile, "%2dC ", i);
              PCHARSV(copybuffer, 0, rc, outfile);
              fprintf(outfile, " (%d)\n", rc);
              }
            }
          }

        cnptr = copynames;
        for (;;)
          {
          int rc;
          char copybuffer[256];

          if (use_pcre16)
            {
            if (*(pcre_uint16 *)cnptr == 0) break;
            }
          else
            {
            if (*(pcre_uint8 *)cnptr == 0) break;
            }

          PCRE_COPY_NAMED_SUBSTRING(rc, re, bptr, use_offsets, count,
            cnptr, copybuffer, sizeof(copybuffer));

          if (rc < 0)
            {
            fprintf(outfile, "copy substring ");
            PCHARSV(cnptr, 0, -1, outfile);
            fprintf(outfile, " failed %d\n", rc);
            }
          else
            {
            fprintf(outfile, "  C ");
            PCHARSV(copybuffer, 0, rc, outfile);
            fprintf(outfile, " (%d) ", rc);
            PCHARSV(cnptr, 0, -1, outfile);
            putc('\n', outfile);
            }

          cnptr = (char *)cnptr + (STRLEN(cnptr) + 1) * CHAR_SIZE;
          }

        for (i = 0; i < 32; i++)
          {
          if ((getstrings & (1 << i)) != 0)
            {
            int rc;
            const char *substring;
            PCRE_GET_SUBSTRING(rc, bptr, use_offsets, count, i, &substring);
            if (rc < 0)
              fprintf(outfile, "get substring %d failed %d\n", i, rc);
            else
              {
              fprintf(outfile, "%2dG ", i);
              PCHARSV(substring, 0, rc, outfile);
              fprintf(outfile, " (%d)\n", rc);
              PCRE_FREE_SUBSTRING(substring);
              }
            }
          }

        gnptr = getnames;
        for (;;)
          {
          int rc;
          const char *substring;

          if (use_pcre16)
            {
            if (*(pcre_uint16 *)gnptr == 0) break;
            }
          else
            {
            if (*(pcre_uint8 *)gnptr == 0) break;
            }

          PCRE_GET_NAMED_SUBSTRING(rc, re, bptr, use_offsets, count,
            gnptr, &substring);
          if (rc < 0)
            {
            fprintf(outfile, "get substring ");
            PCHARSV(gnptr, 0, -1, outfile);
            fprintf(outfile, " failed %d\n", rc);
            }
          else
            {
            fprintf(outfile, "  G ");
            PCHARSV(substring, 0, rc, outfile);
            fprintf(outfile, " (%d) ", rc);
            PCHARSV(gnptr, 0, -1, outfile);
            PCRE_FREE_SUBSTRING(substring);
            putc('\n', outfile);
            }

          gnptr = (char *)gnptr + (STRLEN(gnptr) + 1) * CHAR_SIZE;
          }

        if (getlist)
          {
          int rc;
          const char **stringlist;
          PCRE_GET_SUBSTRING_LIST(rc, bptr, use_offsets, count, &stringlist);
          if (rc < 0)
            fprintf(outfile, "get substring list failed %d\n", rc);
          else
            {
            for (i = 0; i < count; i++)
              {
              fprintf(outfile, "%2dL ", i);
              PCHARSV(stringlist[i], 0, -1, outfile);
              putc('\n', outfile);
              }
            if (stringlist[i] != NULL)
              fprintf(outfile, "string list not terminated by NULL\n");
            PCRE_FREE_SUBSTRING_LIST(stringlist);
            }
          }
        }

      /* There was a partial match */

      else if (count == PCRE_ERROR_PARTIAL)
        {
        if (markptr == NULL) fprintf(outfile, "Partial match");
        else
          {
          fprintf(outfile, "Partial match, mark=");
          PCHARSV(markptr, 0, -1, outfile);
          }
        if (use_size_offsets > 1)
          {
          fprintf(outfile, ": ");
          PCHARSV(bptr, use_offsets[0], use_offsets[1] - use_offsets[0],
            outfile);
          }
        if (verify_jit && jit_was_used) fprintf(outfile, " (JIT)");
        fprintf(outfile, "\n");
        break;  /* Out of the /g loop */
        }

      /* Failed to match. If this is a /g or /G loop and we previously set
      g_notempty after a null match, this is not necessarily the end. We want
      to advance the start offset, and continue. We won't be at the end of the
      string - that was checked before setting g_notempty.

      Complication arises in the case when the newline convention is "any",
      "crlf", or "anycrlf". If the previous match was at the end of a line
      terminated by CRLF, an advance of one character just passes the \r,
      whereas we should prefer the longer newline sequence, as does the code in
      PCREXEC8(). Fudge the offset value to achieve this. We check for a
      newline setting in the pattern; if none was set, use PCRE_CONFIG() to
      find the default.

      Otherwise, in the case of UTF-8 matching, the advance must be one
      character, not one byte. */

      else
        {
        if (g_notempty != 0)
          {
          int onechar = 1;
          unsigned int obits = ((REAL_PCRE *)re)->options;
          use_offsets[0] = start_offset;
          if ((obits & PCRE_NEWLINE_BITS) == 0)
            {
            int d;
            (void)PCRE_CONFIG(PCRE_CONFIG_NEWLINE, &d);
            /* Note that these values are always the ASCII ones, even in
            EBCDIC environments. CR = 13, NL = 10. */
            obits = (d == 13)? PCRE_NEWLINE_CR :
                    (d == 10)? PCRE_NEWLINE_LF :
                    (d == (13<<8 | 10))? PCRE_NEWLINE_CRLF :
                    (d == -2)? PCRE_NEWLINE_ANYCRLF :
                    (d == -1)? PCRE_NEWLINE_ANY : 0;
            }
          if (((obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANY ||
               (obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_CRLF ||
               (obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANYCRLF)
              &&
              start_offset < len - 1 &&
#if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16
              (use_pcre16?
                   ((PCRE_SPTR16)bptr)[start_offset] == '\r'
                && ((PCRE_SPTR16)bptr)[start_offset + 1] == '\n'
              :
                   bptr[start_offset] == '\r'
                && bptr[start_offset + 1] == '\n')
#elif defined SUPPORT_PCRE16
                 ((PCRE_SPTR16)bptr)[start_offset] == '\r'
              && ((PCRE_SPTR16)bptr)[start_offset + 1] == '\n'
#else
                 bptr[start_offset] == '\r'
              && bptr[start_offset + 1] == '\n'
#endif
              )
            onechar++;
          else if (use_utf)
            {
            while (start_offset + onechar < len)
              {
              if ((bptr[start_offset+onechar] & 0xc0) != 0x80) break;
              onechar++;
              }
            }
          use_offsets[1] = start_offset + onechar;
          }
        else
          {
          switch(count)
            {
            case PCRE_ERROR_NOMATCH:
            if (gmatched == 0)
              {
              if (markptr == NULL)
                {
                fprintf(outfile, "No match");
                }
              else
                {
                fprintf(outfile, "No match, mark = ");
                PCHARSV(markptr, 0, -1, outfile);
                }
              if (verify_jit && jit_was_used) fprintf(outfile, " (JIT)");
              putc('\n', outfile);
              }
            break;

            case PCRE_ERROR_BADUTF8:
            case PCRE_ERROR_SHORTUTF8:
            fprintf(outfile, "Error %d (%s UTF-%s string)", count,
              (count == PCRE_ERROR_BADUTF8)? "bad" : "short",
              use_pcre16? "16" : "8");
            if (use_size_offsets >= 2)
              fprintf(outfile, " offset=%d reason=%d", use_offsets[0],
                use_offsets[1]);
            fprintf(outfile, "\n");
            break;

            case PCRE_ERROR_BADUTF8_OFFSET:
            fprintf(outfile, "Error %d (bad UTF-%s offset)\n", count,
              use_pcre16? "16" : "8");
            break;

            default:
            if (count < 0 &&
                (-count) < (int)(sizeof(errtexts)/sizeof(const char *)))
              fprintf(outfile, "Error %d (%s)\n", count, errtexts[-count]);
            else
              fprintf(outfile, "Error %d (Unexpected value)\n", count);
            break;
            }

          break;  /* Out of the /g loop */
          }
        }

      /* If not /g or /G we are done */

      if (!do_g && !do_G) break;

      /* If we have matched an empty string, first check to see if we are at
      the end of the subject. If so, the /g loop is over. Otherwise, mimic what
      Perl's /g options does. This turns out to be rather cunning. First we set
      PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED and try the match again at the
      same point. If this fails (picked up above) we advance to the next
      character. */

      g_notempty = 0;

      if (use_offsets[0] == use_offsets[1])
        {
        if (use_offsets[0] == len) break;
        g_notempty = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED;
        }

      /* For /g, update the start offset, leaving the rest alone */

      if (do_g) start_offset = use_offsets[1];

      /* For /G, update the pointer and length */

      else
        {
        bptr += use_offsets[1] * CHAR_SIZE;
        len -= use_offsets[1];
        }
      }  /* End of loop for /g and /G */

    NEXT_DATA: continue;
    }    /* End of loop for data lines */

  CONTINUE:

#if !defined NOPOSIX
  if (posix || do_posix) regfree(&preg);
#endif

  if (re != NULL) new_free(re);
  if (extra != NULL)
    {
    PCRE_FREE_STUDY(extra);
    }
  if (locale_set)
    {
    new_free((void *)tables);
    setlocale(LC_CTYPE, "C");
    locale_set = 0;
    }
  if (jit_stack != NULL)
    {
    PCRE_JIT_STACK_FREE(jit_stack);
    jit_stack = NULL;
    }
  }

if (infile == stdin) fprintf(outfile, "\n");

EXIT:

if (infile != NULL && infile != stdin) fclose(infile);
if (outfile != NULL && outfile != stdout) fclose(outfile);

free(buffer);
free(dbuffer);
free(pbuffer);
free(offsets);

#ifdef SUPPORT_PCRE16
if (buffer16 != NULL) free(buffer16);
#endif

return yield;
}

/* End of PCRETEST.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcretest.c converted to PCRETEST*/
/*autoconv-0013 PCRETEST line: 41 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRETEST line: 42 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRETEST line: 43 pcretest replaced by PCRETEST*/
/*autoconv-0010 PCRETEST line: 50 added HAVE_CONFIG_H*/
/*autoconv-0011 PCRETEST line: 53 config.h replaced by CONFIG.h*/
/*autoconv-0013 PCRETEST line: 85 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 131 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCRETEST line: 132 pcretest replaced by PCRETEST*/
/*autoconv-0011 PCRETEST line: 139 pcre.h replaced by PCRE.h*/
/*autoconv-0011 PCRETEST line: 146 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 PCRETEST line: 148 pcre_printint replaced by PRINTIN8*/
/*autoconv-0013 PCRETEST line: 150 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRETEST line: 154 pcre_printint replaced by PRINTIN8*/
/*autoconv-0011 PCRETEST line: 166 pcre_tables.c replaced by TABLES8.c*/
/*autoconv-0011 PCRETEST line: 192 pcreposix.h replaced by POSIXH.h*/
/*autoconv-0013 PCRETEST line: 196 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 240 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRETEST line: 252 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 PCRETEST line: 257 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRETEST line: 287 pcre_printint replaced by PRINTIN8*/
/*autoconv-0013 PCRETEST line: 290 pcre_study replaced by STUDY8*/
/*autoconv-0013 PCRETEST line: 391 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRETEST line: 436 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRETEST line: 528 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0013 PCRETEST line: 559 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRETEST line: 573 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0013 PCRETEST line: 671 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 726 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRETEST line: 726 pcre_dfa_exec replaced by DFAEXEC8*/
/*autoconv-0013 PCRETEST line: 1247 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 1364 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 1716 pcre_compile replaced by COMPILE8*/
/*autoconv-0013 PCRETEST line: 1755 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRETEST line: 1758 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRETEST line: 1784 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0013 PCRETEST line: 2139 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 2144 pcretest replaced by PCRETEST*/
/*autoconv-0013 PCRETEST line: 2273 pcre_version replaced by VERSION8*/
/*autoconv-0013 PCRETEST line: 2277 pcre_version replaced by VERSION8*/
/*autoconv-0013 PCRETEST line: 2406 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRETEST line: 2453 pcre_config replaced by CONFIG8*/
/*autoconv-0013 PCRETEST line: 2460 pcre_config replaced by CONFIG8*/
/*autoconv-0015 PCRETEST line: 2649 fopen "rb" replaced by "r"*/
/*autoconv-0013 PCRETEST line: 3157 pcre_fullinfo replaced by FULLINF8*/
/*autoconv-0015 PCRETEST line: 3376 fopen "wb" replaced by "w"*/
/*autoconv-0013 PCRETEST line: 3986 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRETEST line: 4296 pcre_exec replaced by PCREXEC8*/
/*autoconv-0013 PCRETEST line: 4481 pcretest replaced by PCRETEST*/
./ ADD NAME=CONFIG8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This module contains the external function CONFIG8(). */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

/* Keep the original link size. */
static int real_link_size = LINK_SIZE;

#include "INTERNA8.h"


/*************************************************
* Return info about what features are configured *
*************************************************/

/* This function has an extensible interface so that additional items can be
added compatibly.

Arguments:
  what             what information is required
  where            where to put the information

Returns:           0 if data returned, negative on error
*/

#ifdef COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
CONFIG8(int what, void *where)
#else
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_config(int what, void *where)
#endif
{
switch (what)
  {
  case PCRE_CONFIG_UTF8:
#if defined COMPILE_PCRE16
  *((int *)where) = 0;
  return PCRE_ERROR_BADOPTION;
#else
#if defined SUPPORT_UTF
  *((int *)where) = 1;
#else
  *((int *)where) = 0;
#endif
  break;
#endif

  case PCRE_CONFIG_UTF16:
#if defined COMPILE_PCRE8
  *((int *)where) = 0;
  return PCRE_ERROR_BADOPTION;
#else
#if defined SUPPORT_UTF
  *((int *)where) = 1;
#else
  *((int *)where) = 0;
#endif
  break;
#endif

  case PCRE_CONFIG_UNICODE_PROPERTIES:
#ifdef SUPPORT_UCP
  *((int *)where) = 1;
#else
  *((int *)where) = 0;
#endif
  break;

  case PCRE_CONFIG_JIT:
#ifdef SUPPORT_JIT
  *((int *)where) = 1;
#else
  *((int *)where) = 0;
#endif
  break;

  case PCRE_CONFIG_JITTARGET:
#ifdef SUPPORT_JIT
  *((const char **)where) = PRIV(jit_get_target)();
#else
  *((const char **)where) = NULL;
#endif
  break;

  case PCRE_CONFIG_NEWLINE:
  *((int *)where) = NEWLINE;
  break;

  case PCRE_CONFIG_BSR:
#ifdef BSR_ANYCRLF
  *((int *)where) = 1;
#else
  *((int *)where) = 0;
#endif
  break;

  case PCRE_CONFIG_LINK_SIZE:
  *((int *)where) = real_link_size;
  break;

  case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD:
  *((int *)where) = POSIX_MALLOC_THRESHOLD;
  break;

  case PCRE_CONFIG_MATCH_LIMIT:
  *((unsigned long int *)where) = MATCH_LIMIT;
  break;

  case PCRE_CONFIG_MATCH_LIMIT_RECURSION:
  *((unsigned long int *)where) = MATCH_LIMIT_RECURSION;
  break;

  case PCRE_CONFIG_STACKRECURSE:
#ifdef NO_RECURSE
  *((int *)where) = 0;
#else
  *((int *)where) = 1;
#endif
  break;

  default: return PCRE_ERROR_BADOPTION;
  }

return 0;
}

/* End of CONFIG8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_config.c converted to CONFIG8*/
/*autoconv-0013 CONFIG8 line: 41 pcre_config replaced by CONFIG8*/
/*autoconv-0010 CONFIG8 line: 45 added HAVE_CONFIG_H*/
/*autoconv-0011 CONFIG8 line: 48 config.h replaced by CONFIG.h*/
/*autoconv-0011 CONFIG8 line: 54 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 CONFIG8 line: 73 pcre_config replaced by CONFIG8*/
/*autoconv-0013 CONFIG8 line: 173 pcre_config replaced by CONFIG8*/
./ ADD NAME=TABLES8 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

#ifndef PCRE_INCLUDED

/* This module contains some fixed tables that are used by more than one of the
PCRE code modules. The tables are also #included by the PCRETEST program, which
uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name
clashes with the library. */


#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

#endif /* PCRE_INCLUDED */

/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
the definition is next to the definition of the opcodes in pcre_internal.h. */

const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };



/*************************************************
*           Tables for UTF-8 support             *
*************************************************/

/* These are the breakpoints for different numbers of bytes in a UTF-8
character. */

#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \
  || (defined PCRE_INCLUDED && defined SUPPORT_PCRE16)

/* These tables are also required by PCRETEST in 16 bit mode. */

const int PRIV(utf8_table1)[] =
  { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};

const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int);

/* These are the indicator bits and the mask for the data bits to set in the
first byte of a character, indexed by the number of additional bytes. */

const int PRIV(utf8_table2)[] = { 0,    0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};

/* Table of the number of extra bytes, indexed by the first byte masked with
0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */

const pcre_uint8 PRIV(utf8_table4)[] = {
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };

#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE16)*/

#ifdef SUPPORT_UTF

/* Table to translate from particular type value to the general value. */

const int PRIV(ucp_gentype)[] = {
  ucp_C, ucp_C, ucp_C, ucp_C, ucp_C,  /* Cc, Cf, Cn, Co, Cs */
  ucp_L, ucp_L, ucp_L, ucp_L, ucp_L,  /* Ll, Lu, Lm, Lo, Lt */
  ucp_M, ucp_M, ucp_M,                /* Mc, Me, Mn */
  ucp_N, ucp_N, ucp_N,                /* Nd, Nl, No */
  ucp_P, ucp_P, ucp_P, ucp_P, ucp_P,  /* Pc, Pd, Pe, Pf, Pi */
  ucp_P, ucp_P,                       /* Ps, Po */
  ucp_S, ucp_S, ucp_S, ucp_S,         /* Sc, Sk, Sm, So */
  ucp_Z, ucp_Z, ucp_Z                 /* Zl, Zp, Zs */
};

#ifdef SUPPORT_JIT
/* This table reverses PRIV(ucp_gentype). We can save the cost
of a memory load. */

const int PRIV(ucp_typerange)[] = {
  ucp_Cc, ucp_Cs,
  ucp_Ll, ucp_Lu,
  ucp_Mc, ucp_Mn,
  ucp_Nd, ucp_No,
  ucp_Pc, ucp_Ps,
  ucp_Sc, ucp_So,
  ucp_Zl, ucp_Zs,
};
#endif /* SUPPORT_JIT */

/* The pcre_utt[] table below translates Unicode property names into type and
code values. It is searched by binary chop, so must be in collating sequence of
name. Originally, the table contained pointers to the name strings in the first
field of each entry. However, that leads to a large number of relocations when
a shared library is dynamically loaded. A significant reduction is made by
putting all the names into a single, large string and then using offsets in the
table itself. Maintenance is more error-prone, but frequent changes to this
data are unlikely.

July 2008: There is now a script called maint/GenerateUtt.py that can be used
to generate this data automatically instead of maintaining it by hand.

The script was updated in March 2009 to generate a new EBCDIC-compliant
version. Like all other character and string literals that are compared against
the regular expression pattern, we must use STR_ macros instead of literal
strings to make sure that UTF-8 support works on EBCDIC platforms. */

#define STRING_Any0 STR_A STR_n STR_y "\0"
#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0"
#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"
#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0"
#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"
#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0"
#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0"
#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0"
#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"
#define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0"
#define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0"
#define STRING_Buginese0 STR_B STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"
#define STRING_Buhid0 STR_B STR_u STR_h STR_i STR_d "\0"
#define STRING_C0 STR_C "\0"
#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"
#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0"
#define STRING_Cc0 STR_C STR_c "\0"
#define STRING_Cf0 STR_C STR_f "\0"
#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"
#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0"
#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"
#define STRING_Cn0 STR_C STR_n "\0"
#define STRING_Co0 STR_C STR_o "\0"
#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0"
#define STRING_Coptic0 STR_C STR_o STR_p STR_t STR_i STR_c "\0"
#define STRING_Cs0 STR_C STR_s "\0"
#define STRING_Cuneiform0 STR_C STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"
#define STRING_Cypriot0 STR_C STR_y STR_p STR_r STR_i STR_o STR_t "\0"
#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"
#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"
#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"
#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0"
#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0"
#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
#define STRING_Han0 STR_H STR_a STR_n "\0"
#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0"
#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0"
#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0"
#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"
#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0"
#define STRING_Inherited0 STR_I STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"
#define STRING_Inscriptional_Pahlavi0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"
#define STRING_Inscriptional_Parthian0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"
#define STRING_Javanese0 STR_J STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"
#define STRING_Kaithi0 STR_K STR_a STR_i STR_t STR_h STR_i "\0"
#define STRING_Kannada0 STR_K STR_a STR_n STR_n STR_a STR_d STR_a "\0"
#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"
#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0"
#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0"
#define STRING_L0 STR_L "\0"
#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0"
#define STRING_Lao0 STR_L STR_a STR_o "\0"
#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0"
#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0"
#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0"
#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0"
#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0"
#define STRING_Ll0 STR_L STR_l "\0"
#define STRING_Lm0 STR_L STR_m "\0"
#define STRING_Lo0 STR_L STR_o "\0"
#define STRING_Lt0 STR_L STR_t "\0"
#define STRING_Lu0 STR_L STR_u "\0"
#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0"
#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0"
#define STRING_M0 STR_M "\0"
#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"
#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0"
#define STRING_Mc0 STR_M STR_c "\0"
#define STRING_Me0 STR_M STR_e "\0"
#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"
#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"
#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0"
#define STRING_Mn0 STR_M STR_n "\0"
#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
#define STRING_N0 STR_N "\0"
#define STRING_Nd0 STR_N STR_d "\0"
#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0"
#define STRING_Nko0 STR_N STR_k STR_o "\0"
#define STRING_Nl0 STR_N STR_l "\0"
#define STRING_No0 STR_N STR_o "\0"
#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0"
#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0"
#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0"
#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0"
#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0"
#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0"
#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0"
#define STRING_P0 STR_P "\0"
#define STRING_Pc0 STR_P STR_c "\0"
#define STRING_Pd0 STR_P STR_d "\0"
#define STRING_Pe0 STR_P STR_e "\0"
#define STRING_Pf0 STR_P STR_f "\0"
#define STRING_Phags_Pa0 STR_P STR_h STR_a STR_g STR_s STR_UNDERSCORE STR_P STR_a "\0"
#define STRING_Phoenician0 STR_P STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"
#define STRING_Pi0 STR_P STR_i "\0"
#define STRING_Po0 STR_P STR_o "\0"
#define STRING_Ps0 STR_P STR_s "\0"
#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0"
#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0"
#define STRING_S0 STR_S "\0"
#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"
#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"
#define STRING_Sc0 STR_S STR_c "\0"
#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"
#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"
#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"
#define STRING_Sk0 STR_S STR_k "\0"
#define STRING_Sm0 STR_S STR_m "\0"
#define STRING_So0 STR_S STR_o "\0"
#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0"
#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0"
#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0"
#define STRING_Tagalog0 STR_T STR_a STR_g STR_a STR_l STR_o STR_g "\0"
#define STRING_Tagbanwa0 STR_T STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"
#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0"
#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0"
#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0"
#define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0"
#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0"
#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0"
#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0"
#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0"
#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0"
#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"
#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
#define STRING_Vai0 STR_V STR_a STR_i "\0"
#define STRING_Xan0 STR_X STR_a STR_n "\0"
#define STRING_Xps0 STR_X STR_p STR_s "\0"
#define STRING_Xsp0 STR_X STR_s STR_p "\0"
#define STRING_Xwd0 STR_X STR_w STR_d "\0"
#define STRING_Yi0 STR_Y STR_i "\0"
#define STRING_Z0 STR_Z "\0"
#define STRING_Zl0 STR_Z STR_l "\0"
#define STRING_Zp0 STR_Z STR_p "\0"
#define STRING_Zs0 STR_Z STR_s "\0"

const char PRIV(utt_names)[] =
  STRING_Any0
  STRING_Arabic0
  STRING_Armenian0
  STRING_Avestan0
  STRING_Balinese0
  STRING_Bamum0
  STRING_Batak0
  STRING_Bengali0
  STRING_Bopomofo0
  STRING_Brahmi0
  STRING_Braille0
  STRING_Buginese0
  STRING_Buhid0
  STRING_C0
  STRING_Canadian_Aboriginal0
  STRING_Carian0
  STRING_Cc0
  STRING_Cf0
  STRING_Chakma0
  STRING_Cham0
  STRING_Cherokee0
  STRING_Cn0
  STRING_Co0
  STRING_Common0
  STRING_Coptic0
  STRING_Cs0
  STRING_Cuneiform0
  STRING_Cypriot0
  STRING_Cyrillic0
  STRING_Deseret0
  STRING_Devanagari0
  STRING_Egyptian_Hieroglyphs0
  STRING_Ethiopic0
  STRING_Georgian0
  STRING_Glagolitic0
  STRING_Gothic0
  STRING_Greek0
  STRING_Gujarati0
  STRING_Gurmukhi0
  STRING_Han0
  STRING_Hangul0
  STRING_Hanunoo0
  STRING_Hebrew0
  STRING_Hiragana0
  STRING_Imperial_Aramaic0
  STRING_Inherited0
  STRING_Inscriptional_Pahlavi0
  STRING_Inscriptional_Parthian0
  STRING_Javanese0
  STRING_Kaithi0
  STRING_Kannada0
  STRING_Katakana0
  STRING_Kayah_Li0
  STRING_Kharoshthi0
  STRING_Khmer0
  STRING_L0
  STRING_L_AMPERSAND0
  STRING_Lao0
  STRING_Latin0
  STRING_Lepcha0
  STRING_Limbu0
  STRING_Linear_B0
  STRING_Lisu0
  STRING_Ll0
  STRING_Lm0
  STRING_Lo0
  STRING_Lt0
  STRING_Lu0
  STRING_Lycian0
  STRING_Lydian0
  STRING_M0
  STRING_Malayalam0
  STRING_Mandaic0
  STRING_Mc0
  STRING_Me0
  STRING_Meetei_Mayek0
  STRING_Meroitic_Cursive0
  STRING_Meroitic_Hieroglyphs0
  STRING_Miao0
  STRING_Mn0
  STRING_Mongolian0
  STRING_Myanmar0
  STRING_N0
  STRING_Nd0
  STRING_New_Tai_Lue0
  STRING_Nko0
  STRING_Nl0
  STRING_No0
  STRING_Ogham0
  STRING_Ol_Chiki0
  STRING_Old_Italic0
  STRING_Old_Persian0
  STRING_Old_South_Arabian0
  STRING_Old_Turkic0
  STRING_Oriya0
  STRING_Osmanya0
  STRING_P0
  STRING_Pc0
  STRING_Pd0
  STRING_Pe0
  STRING_Pf0
  STRING_Phags_Pa0
  STRING_Phoenician0
  STRING_Pi0
  STRING_Po0
  STRING_Ps0
  STRING_Rejang0
  STRING_Runic0
  STRING_S0
  STRING_Samaritan0
  STRING_Saurashtra0
  STRING_Sc0
  STRING_Sharada0
  STRING_Shavian0
  STRING_Sinhala0
  STRING_Sk0
  STRING_Sm0
  STRING_So0
  STRING_Sora_Sompeng0
  STRING_Sundanese0
  STRING_Syloti_Nagri0
  STRING_Syriac0
  STRING_Tagalog0
  STRING_Tagbanwa0
  STRING_Tai_Le0
  STRING_Tai_Tham0
  STRING_Tai_Viet0
  STRING_Takri0
  STRING_Tamil0
  STRING_Telugu0
  STRING_Thaana0
  STRING_Thai0
  STRING_Tibetan0
  STRING_Tifinagh0
  STRING_Ugaritic0
  STRING_Vai0
  STRING_Xan0
  STRING_Xps0
  STRING_Xsp0
  STRING_Xwd0
  STRING_Yi0
  STRING_Z0
  STRING_Zl0
  STRING_Zp0
  STRING_Zs0;

const ucp_type_table PRIV(utt)[] = {
  {   0, PT_ANY, 0 },
  {   4, PT_SC, ucp_Arabic },
  {  11, PT_SC, ucp_Armenian },
  {  20, PT_SC, ucp_Avestan },
  {  28, PT_SC, ucp_Balinese },
  {  37, PT_SC, ucp_Bamum },
  {  43, PT_SC, ucp_Batak },
  {  49, PT_SC, ucp_Bengali },
  {  57, PT_SC, ucp_Bopomofo },
  {  66, PT_SC, ucp_Brahmi },
  {  73, PT_SC, ucp_Braille },
  {  81, PT_SC, ucp_Buginese },
  {  90, PT_SC, ucp_Buhid },
  {  96, PT_GC, ucp_C },
  {  98, PT_SC, ucp_Canadian_Aboriginal },
  { 118, PT_SC, ucp_Carian },
  { 125, PT_PC, ucp_Cc },
  { 128, PT_PC, ucp_Cf },
  { 131, PT_SC, ucp_Chakma },
  { 138, PT_SC, ucp_Cham },
  { 143, PT_SC, ucp_Cherokee },
  { 152, PT_PC, ucp_Cn },
  { 155, PT_PC, ucp_Co },
  { 158, PT_SC, ucp_Common },
  { 165, PT_SC, ucp_Coptic },
  { 172, PT_PC, ucp_Cs },
  { 175, PT_SC, ucp_Cuneiform },
  { 185, PT_SC, ucp_Cypriot },
  { 193, PT_SC, ucp_Cyrillic },
  { 202, PT_SC, ucp_Deseret },
  { 210, PT_SC, ucp_Devanagari },
  { 221, PT_SC, ucp_Egyptian_Hieroglyphs },
  { 242, PT_SC, ucp_Ethiopic },
  { 251, PT_SC, ucp_Georgian },
  { 260, PT_SC, ucp_Glagolitic },
  { 271, PT_SC, ucp_Gothic },
  { 278, PT_SC, ucp_Greek },
  { 284, PT_SC, ucp_Gujarati },
  { 293, PT_SC, ucp_Gurmukhi },
  { 302, PT_SC, ucp_Han },
  { 306, PT_SC, ucp_Hangul },
  { 313, PT_SC, ucp_Hanunoo },
  { 321, PT_SC, ucp_Hebrew },
  { 328, PT_SC, ucp_Hiragana },
  { 337, PT_SC, ucp_Imperial_Aramaic },
  { 354, PT_SC, ucp_Inherited },
  { 364, PT_SC, ucp_Inscriptional_Pahlavi },
  { 386, PT_SC, ucp_Inscriptional_Parthian },
  { 409, PT_SC, ucp_Javanese },
  { 418, PT_SC, ucp_Kaithi },
  { 425, PT_SC, ucp_Kannada },
  { 433, PT_SC, ucp_Katakana },
  { 442, PT_SC, ucp_Kayah_Li },
  { 451, PT_SC, ucp_Kharoshthi },
  { 462, PT_SC, ucp_Khmer },
  { 468, PT_GC, ucp_L },
  { 470, PT_LAMP, 0 },
  { 473, PT_SC, ucp_Lao },
  { 477, PT_SC, ucp_Latin },
  { 483, PT_SC, ucp_Lepcha },
  { 490, PT_SC, ucp_Limbu },
  { 496, PT_SC, ucp_Linear_B },
  { 505, PT_SC, ucp_Lisu },
  { 510, PT_PC, ucp_Ll },
  { 513, PT_PC, ucp_Lm },
  { 516, PT_PC, ucp_Lo },
  { 519, PT_PC, ucp_Lt },
  { 522, PT_PC, ucp_Lu },
  { 525, PT_SC, ucp_Lycian },
  { 532, PT_SC, ucp_Lydian },
  { 539, PT_GC, ucp_M },
  { 541, PT_SC, ucp_Malayalam },
  { 551, PT_SC, ucp_Mandaic },
  { 559, PT_PC, ucp_Mc },
  { 562, PT_PC, ucp_Me },
  { 565, PT_SC, ucp_Meetei_Mayek },
  { 578, PT_SC, ucp_Meroitic_Cursive },
  { 595, PT_SC, ucp_Meroitic_Hieroglyphs },
  { 616, PT_SC, ucp_Miao },
  { 621, PT_PC, ucp_Mn },
  { 624, PT_SC, ucp_Mongolian },
  { 634, PT_SC, ucp_Myanmar },
  { 642, PT_GC, ucp_N },
  { 644, PT_PC, ucp_Nd },
  { 647, PT_SC, ucp_New_Tai_Lue },
  { 659, PT_SC, ucp_Nko },
  { 663, PT_PC, ucp_Nl },
  { 666, PT_PC, ucp_No },
  { 669, PT_SC, ucp_Ogham },
  { 675, PT_SC, ucp_Ol_Chiki },
  { 684, PT_SC, ucp_Old_Italic },
  { 695, PT_SC, ucp_Old_Persian },
  { 707, PT_SC, ucp_Old_South_Arabian },
  { 725, PT_SC, ucp_Old_Turkic },
  { 736, PT_SC, ucp_Oriya },
  { 742, PT_SC, ucp_Osmanya },
  { 750, PT_GC, ucp_P },
  { 752, PT_PC, ucp_Pc },
  { 755, PT_PC, ucp_Pd },
  { 758, PT_PC, ucp_Pe },
  { 761, PT_PC, ucp_Pf },
  { 764, PT_SC, ucp_Phags_Pa },
  { 773, PT_SC, ucp_Phoenician },
  { 784, PT_PC, ucp_Pi },
  { 787, PT_PC, ucp_Po },
  { 790, PT_PC, ucp_Ps },
  { 793, PT_SC, ucp_Rejang },
  { 800, PT_SC, ucp_Runic },
  { 806, PT_GC, ucp_S },
  { 808, PT_SC, ucp_Samaritan },
  { 818, PT_SC, ucp_Saurashtra },
  { 829, PT_PC, ucp_Sc },
  { 832, PT_SC, ucp_Sharada },
  { 840, PT_SC, ucp_Shavian },
  { 848, PT_SC, ucp_Sinhala },
  { 856, PT_PC, ucp_Sk },
  { 859, PT_PC, ucp_Sm },
  { 862, PT_PC, ucp_So },
  { 865, PT_SC, ucp_Sora_Sompeng },
  { 878, PT_SC, ucp_Sundanese },
  { 888, PT_SC, ucp_Syloti_Nagri },
  { 901, PT_SC, ucp_Syriac },
  { 908, PT_SC, ucp_Tagalog },
  { 916, PT_SC, ucp_Tagbanwa },
  { 925, PT_SC, ucp_Tai_Le },
  { 932, PT_SC, ucp_Tai_Tham },
  { 941, PT_SC, ucp_Tai_Viet },
  { 950, PT_SC, ucp_Takri },
  { 956, PT_SC, ucp_Tamil },
  { 962, PT_SC, ucp_Telugu },
  { 969, PT_SC, ucp_Thaana },
  { 976, PT_SC, ucp_Thai },
  { 981, PT_SC, ucp_Tibetan },
  { 989, PT_SC, ucp_Tifinagh },
  { 998, PT_SC, ucp_Ugaritic },
  { 1007, PT_SC, ucp_Vai },
  { 1011, PT_ALNUM, 0 },
  { 1015, PT_PXSPACE, 0 },
  { 1019, PT_SPACE, 0 },
  { 1023, PT_WORD, 0 },
  { 1027, PT_SC, ucp_Yi },
  { 1030, PT_GC, ucp_Z },
  { 1032, PT_PC, ucp_Zl },
  { 1035, PT_PC, ucp_Zp },
  { 1038, PT_PC, ucp_Zs }
};

const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);

#endif /* SUPPORT_UTF */

/* End of TABLES8.c */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_tables.c converted to TABLES8*/
/*autoconv-0013 TABLES8 line: 43 pcretest replaced by PCRETEST*/
/*autoconv-0010 TABLES8 line: 49 added HAVE_CONFIG_H*/
/*autoconv-0011 TABLES8 line: 52 config.h replaced by CONFIG.h*/
/*autoconv-0011 TABLES8 line: 55 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 TABLES8 line: 76 pcretest replaced by PCRETEST*/
/*autoconv-0013 TABLES8 line: 592 pcre_tables replaced by TABLES8*/
./ ADD NAME=SCANNERH 
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sanjay Ghemawat
//
// Regular-expression based scanner for parsing an input stream.
//
// Example 1: parse a sequence of "var = number" entries from input:
//
//      Scanner scanner(input);
//      string var;
//      int number;
//      scanner.SetSkipExpression("\\s+"); // Skip any white space we encounter
//      while (scanner.Consume("(\\w+) = (\\d+)", &var, &number)) {
//        ...;
//      }

#ifndef _PCRE_SCANNER_H
#define _PCRE_SCANNER_H

#include <assert.h>
#include <string>
#include <vector>

#include <CPPH.h>
#include <pcre_stringpiece.h>

namespace PCRECPP {

class PCRECPP_EXP_DEFN Scanner {
 public:
  Scanner();
  explicit Scanner(const std::string& input);
  ~Scanner();

  // Return current line number.  The returned line-number is
  // one-based.  I.e. it returns 1 + the number of consumed newlines.
  //
  // Note: this method may be slow.  It may take time proportional to
  // the size of the input.
  int LineNumber() const;

  // Return the byte-offset that the scanner is looking in the
  // input data;
  int Offset() const;

  // Return true iff the start of the remaining input matches "re"
  bool LookingAt(const RE& re) const;

  // Return true iff all of the following are true
  //    a. the start of the remaining input matches "re",
  //    b. if any arguments are supplied, matched sub-patterns can be
  //       parsed and stored into the arguments.
  // If it returns true, it skips over the matched input and any
  // following input that matches the "skip" regular expression.
  bool Consume(const RE& re,
               const Arg& arg0 = RE::no_arg,
               const Arg& arg1 = RE::no_arg,
               const Arg& arg2 = RE::no_arg
               // TODO: Allow more arguments?
               );

  // Set the "skip" regular expression.  If after consuming some data,
  // a prefix of the input matches this RE, it is automatically
  // skipped.  For example, a programming language scanner would use
  // a skip RE that matches white space and comments.
  //
  //    scanner.SetSkipExpression("\\s+|//.*|/[*](.|\n)*?[*]/");
  //
  // Skipping repeats as long as it succeeds.  We used to let people do
  // this by writing "(...)*" in the regular expression, but that added
  // up to lots of recursive calls within the pcre library, so now we
  // control repetition explicitly via the function call API.
  //
  // You can pass NULL for "re" if you do not want any data to be skipped.
  void Skip(const char* re);   // DEPRECATED; does *not* repeat
  void SetSkipExpression(const char* re);

  // Temporarily pause "skip"ing. This
  //   Skip("Foo"); code ; DisableSkip(); code; EnableSkip()
  // is similar to
  //   Skip("Foo"); code ; Skip(NULL); code ; Skip("Foo");
  // but avoids creating/deleting new RE objects.
  void DisableSkip();

  // Reenable previously paused skipping.  Any prefix of the input
  // that matches the skip pattern is immediately dropped.
  void EnableSkip();

  /***** Special wrappers around SetSkip() for some common idioms *****/

  // Arranges to skip whitespace, C comments, C++ comments.
  // The overall RE is a disjunction of the following REs:
  //    \\s                     whitespace
  //    //.*\n                  C++ comment
  //    /[*](.|\n)*?[*]/        C comment (x*? means minimal repetitions of x)
  // We get repetition via the semantics of SetSkipExpression, not by using *
  void SkipCXXComments() {
    SetSkipExpression("\\s|//.*\n|/[*](?:\n|.)*?[*]/");
  }

  void set_save_comments(bool comments) {
    save_comments_ = comments;
  }

  bool save_comments() {
    return save_comments_;
  }

  // Append to vector ranges the comments found in the
  // byte range [start,end] (inclusive) of the input data.
  // Only comments that were extracted entirely within that
  // range are returned: no range splitting of atomically-extracted
  // comments is performed.
  void GetComments(int start, int end, std::vector<StringPiece> *ranges);

  // Append to vector ranges the comments added
  // since the last time this was called. This
  // functionality is provided for efficiency when
  // interleaving scanning with parsing.
  void GetNextComments(std::vector<StringPiece> *ranges);

 private:
  std::string   data_;          // All the input data
  StringPiece   input_;         // Unprocessed input
  RE*           skip_;          // If non-NULL, RE for skipping input
  bool          should_skip_;   // If true, use skip_
  bool          skip_repeat_;   // If true, repeat skip_ as long as it works
  bool          save_comments_; // If true, aggregate the skip expression

  // the skipped comments
  // TODO: later consider requiring that the StringPieces be added
  // in order by their start position
  std::vector<StringPiece> *comments_;

  // the offset into comments_ that has been returned by GetNextComments
  int           comments_offset_;

  // helper function to consume *skip_ and honour
  // save_comments_
  void ConsumeSkip();
};

}   // namespace PCRECPP

#endif /* _PCRE_SCANNER_H */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_scanner.h converted to SCANNERH*/
/*autoconv-0011 SCANNERH line: 51 pcrecpp.h replaced by CPPH.h*/
/*autoconv-0013 SCANNERH line: 54 pcrecpp replaced by PCRECPP*/
/*autoconv-0013 SCANNERH line: 170 pcrecpp replaced by PCRECPP*/
./ ADD NAME=PCREUCD8 
#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include "INTERNA8.h"

/* Unicode character database. */
/* This file was autogenerated by the MultiStage2.py script. */
/* Total size: 62904 bytes, block size: 128. */

/* The tables herein are needed only when UCP support is built */
/* into PCRE. This module should not be referenced otherwise, so */
/* it should not matter whether it is compiled or not. However */
/* a comment was received about space saving - maybe the guy linked */
/* all the modules rather than using a library - so we include a */
/* condition to cut out the tables when not needed. But don't leave */
/* a totally empty module because some compilers barf at that. */
/* Instead, just supply small dummy tables. */

#ifndef SUPPORT_UCP
const ucd_record PRIV(ucd_records)[] = {{0,0,0 }};
const pcre_uint8 PRIV(ucd_stage1)[] = {0};
const pcre_uint16 PRIV(ucd_stage2)[] = {0};
#else

/* When recompiling tables with a new Unicode version,
please check types in the structure definition from pcre_internal.h:
typedef struct {
pcre_uint8 property_0;
pcre_uint8 property_1;
pcre_int32 property_2;
} ucd_record; */


const ucd_record PRIV(ucd_records)[] = { /* 4536 bytes, record size 8 */
  {     9,      0,      0, }, /*   0 */
  {     9,     29,      0, }, /*   1 */
  {     9,     21,      0, }, /*   2 */
  {     9,     23,      0, }, /*   3 */
  {     9,     22,      0, }, /*   4 */
  {     9,     18,      0, }, /*   5 */
  {     9,     25,      0, }, /*   6 */
  {     9,     17,      0, }, /*   7 */
  {     9,     13,      0, }, /*   8 */
  {    33,      9,     32, }, /*   9 */
  {     9,     24,      0, }, /*  10 */
  {     9,     16,      0, }, /*  11 */
  {    33,      5,    -32, }, /*  12 */
  {     9,     26,      0, }, /*  13 */
  {    33,      7,      0, }, /*  14 */
  {     9,     20,      0, }, /*  15 */
  {     9,      1,      0, }, /*  16 */
  {     9,     15,      0, }, /*  17 */
  {     9,      5,    743, }, /*  18 */
  {     9,     19,      0, }, /*  19 */
  {    33,      5,      0, }, /*  20 */
  {    33,      5,    121, }, /*  21 */
  {    33,      9,      1, }, /*  22 */
  {    33,      5,     -1, }, /*  23 */
  {    33,      9,   -199, }, /*  24 */
  {    33,      5,   -232, }, /*  25 */
  {    33,      9,   -121, }, /*  26 */
  {    33,      5,   -300, }, /*  27 */
  {    33,      5,    195, }, /*  28 */
  {    33,      9,    210, }, /*  29 */
  {    33,      9,    206, }, /*  30 */
  {    33,      9,    205, }, /*  31 */
  {    33,      9,     79, }, /*  32 */
  {    33,      9,    202, }, /*  33 */
  {    33,      9,    203, }, /*  34 */
  {    33,      9,    207, }, /*  35 */
  {    33,      5,     97, }, /*  36 */
  {    33,      9,    211, }, /*  37 */
  {    33,      9,    209, }, /*  38 */
  {    33,      5,    163, }, /*  39 */
  {    33,      9,    213, }, /*  40 */
  {    33,      5,    130, }, /*  41 */
  {    33,      9,    214, }, /*  42 */
  {    33,      9,    218, }, /*  43 */
  {    33,      9,    217, }, /*  44 */
  {    33,      9,    219, }, /*  45 */
  {    33,      5,     56, }, /*  46 */
  {    33,      9,      2, }, /*  47 */
  {    33,      8,     -1, }, /*  48 */
  {    33,      5,     -2, }, /*  49 */
  {    33,      5,    -79, }, /*  50 */
  {    33,      9,    -97, }, /*  51 */
  {    33,      9,    -56, }, /*  52 */
  {    33,      9,   -130, }, /*  53 */
  {    33,      9,  10795, }, /*  54 */
  {    33,      9,   -163, }, /*  55 */
  {    33,      9,  10792, }, /*  56 */
  {    33,      5,  10815, }, /*  57 */
  {    33,      9,   -195, }, /*  58 */
  {    33,      9,     69, }, /*  59 */
  {    33,      9,     71, }, /*  60 */
  {    33,      5,  10783, }, /*  61 */
  {    33,      5,  10780, }, /*  62 */
  {    33,      5,  10782, }, /*  63 */
  {    33,      5,   -210, }, /*  64 */
  {    33,      5,   -206, }, /*  65 */
  {    33,      5,   -205, }, /*  66 */
  {    33,      5,   -202, }, /*  67 */
  {    33,      5,   -203, }, /*  68 */
  {    33,      5,   -207, }, /*  69 */
  {    33,      5,  42280, }, /*  70 */
  {    33,      5,  42308, }, /*  71 */
  {    33,      5,   -209, }, /*  72 */
  {    33,      5,   -211, }, /*  73 */
  {    33,      5,  10743, }, /*  74 */
  {    33,      5,  10749, }, /*  75 */
  {    33,      5,   -213, }, /*  76 */
  {    33,      5,   -214, }, /*  77 */
  {    33,      5,  10727, }, /*  78 */
  {    33,      5,   -218, }, /*  79 */
  {    33,      5,    -69, }, /*  80 */
  {    33,      5,   -217, }, /*  81 */
  {    33,      5,    -71, }, /*  82 */
  {    33,      5,   -219, }, /*  83 */
  {    33,      6,      0, }, /*  84 */
  {     9,      6,      0, }, /*  85 */
  {     3,     24,      0, }, /*  86 */
  {    27,     12,      0, }, /*  87 */
  {    27,     12,     84, }, /*  88 */
  {    19,      9,      1, }, /*  89 */
  {    19,      5,     -1, }, /*  90 */
  {    19,     24,      0, }, /*  91 */
  {     9,      2,      0, }, /*  92 */
  {    19,      6,      0, }, /*  93 */
  {    19,      5,    130, }, /*  94 */
  {    19,      9,     38, }, /*  95 */
  {    19,      9,     37, }, /*  96 */
  {    19,      9,     64, }, /*  97 */
  {    19,      9,     63, }, /*  98 */
  {    19,      5,      0, }, /*  99 */
  {    19,      9,     32, }, /* 100 */
  {    19,      5,    -38, }, /* 101 */
  {    19,      5,    -37, }, /* 102 */
  {    19,      5,    -32, }, /* 103 */
  {    19,      5,    -31, }, /* 104 */
  {    19,      5,    -64, }, /* 105 */
  {    19,      5,    -63, }, /* 106 */
  {    19,      9,      8, }, /* 107 */
  {    19,      5,    -62, }, /* 108 */
  {    19,      5,    -57, }, /* 109 */
  {    19,      9,      0, }, /* 110 */
  {    19,      5,    -47, }, /* 111 */
  {    19,      5,    -54, }, /* 112 */
  {    19,      5,     -8, }, /* 113 */
  {    10,      9,      1, }, /* 114 */
  {    10,      5,     -1, }, /* 115 */
  {    19,      5,    -86, }, /* 116 */
  {    19,      5,    -80, }, /* 117 */
  {    19,      5,      7, }, /* 118 */
  {    19,      9,    -60, }, /* 119 */
  {    19,      5,    -96, }, /* 120 */
  {    19,     25,      0, }, /* 121 */
  {    19,      9,     -7, }, /* 122 */
  {    19,      9,   -130, }, /* 123 */
  {    12,      9,     80, }, /* 124 */
  {    12,      9,     32, }, /* 125 */
  {    12,      5,    -32, }, /* 126 */
  {    12,      5,    -80, }, /* 127 */
  {    12,      9,      1, }, /* 128 */
  {    12,      5,     -1, }, /* 129 */
  {    12,     26,      0, }, /* 130 */
  {    12,     12,      0, }, /* 131 */
  {    12,     11,      0, }, /* 132 */
  {    12,      9,     15, }, /* 133 */
  {    12,      5,    -15, }, /* 134 */
  {     1,      9,     48, }, /* 135 */
  {     1,      6,      0, }, /* 136 */
  {     1,     21,      0, }, /* 137 */
  {     1,      5,    -48, }, /* 138 */
  {     1,      5,      0, }, /* 139 */
  {     1,     17,      0, }, /* 140 */
  {     1,     23,      0, }, /* 141 */
  {    25,     12,      0, }, /* 142 */
  {    25,     17,      0, }, /* 143 */
  {    25,     21,      0, }, /* 144 */
  {    25,      7,      0, }, /* 145 */
  {     0,      1,      0, }, /* 146 */
  {     0,     25,      0, }, /* 147 */
  {     0,     21,      0, }, /* 148 */
  {     0,     23,      0, }, /* 149 */
  {     0,     26,      0, }, /* 150 */
  {     0,     12,      0, }, /* 151 */
  {     0,      7,      0, }, /* 152 */
  {     0,      6,      0, }, /* 153 */
  {     0,     13,      0, }, /* 154 */
  {    49,     21,      0, }, /* 155 */
  {    49,      1,      0, }, /* 156 */
  {    49,      7,      0, }, /* 157 */
  {    49,     12,      0, }, /* 158 */
  {    55,      7,      0, }, /* 159 */
  {    55,     12,      0, }, /* 160 */
  {    63,     13,      0, }, /* 161 */
  {    63,      7,      0, }, /* 162 */
  {    63,     12,      0, }, /* 163 */
  {    63,      6,      0, }, /* 164 */
  {    63,     26,      0, }, /* 165 */
  {    63,     21,      0, }, /* 166 */
  {    89,      7,      0, }, /* 167 */
  {    89,     12,      0, }, /* 168 */
  {    89,      6,      0, }, /* 169 */
  {    89,     21,      0, }, /* 170 */
  {    94,      7,      0, }, /* 171 */
  {    94,     12,      0, }, /* 172 */
  {    94,     21,      0, }, /* 173 */
  {    14,     12,      0, }, /* 174 */
  {    14,     10,      0, }, /* 175 */
  {    14,      7,      0, }, /* 176 */
  {    14,     13,      0, }, /* 177 */
  {    14,     21,      0, }, /* 178 */
  {    14,      6,      0, }, /* 179 */
  {     2,     12,      0, }, /* 180 */
  {     2,     10,      0, }, /* 181 */
  {     2,      7,      0, }, /* 182 */
  {     2,     13,      0, }, /* 183 */
  {     2,     23,      0, }, /* 184 */
  {     2,     15,      0, }, /* 185 */
  {     2,     26,      0, }, /* 186 */
  {    21,     12,      0, }, /* 187 */
  {    21,     10,      0, }, /* 188 */
  {    21,      7,      0, }, /* 189 */
  {    21,     13,      0, }, /* 190 */
  {    20,     12,      0, }, /* 191 */
  {    20,     10,      0, }, /* 192 */
  {    20,      7,      0, }, /* 193 */
  {    20,     13,      0, }, /* 194 */
  {    20,     21,      0, }, /* 195 */
  {    20,     23,      0, }, /* 196 */
  {    43,     12,      0, }, /* 197 */
  {    43,     10,      0, }, /* 198 */
  {    43,      7,      0, }, /* 199 */
  {    43,     13,      0, }, /* 200 */
  {    43,     26,      0, }, /* 201 */
  {    43,     15,      0, }, /* 202 */
  {    53,     12,      0, }, /* 203 */
  {    53,      7,      0, }, /* 204 */
  {    53,     10,      0, }, /* 205 */
  {    53,     13,      0, }, /* 206 */
  {    53,     15,      0, }, /* 207 */
  {    53,     26,      0, }, /* 208 */
  {    53,     23,      0, }, /* 209 */
  {    54,     10,      0, }, /* 210 */
  {    54,      7,      0, }, /* 211 */
  {    54,     12,      0, }, /* 212 */
  {    54,     13,      0, }, /* 213 */
  {    54,     15,      0, }, /* 214 */
  {    54,     26,      0, }, /* 215 */
  {    28,     10,      0, }, /* 216 */
  {    28,      7,      0, }, /* 217 */
  {    28,     12,      0, }, /* 218 */
  {    28,     13,      0, }, /* 219 */
  {    36,     10,      0, }, /* 220 */
  {    36,      7,      0, }, /* 221 */
  {    36,     12,      0, }, /* 222 */
  {    36,     13,      0, }, /* 223 */
  {    36,     15,      0, }, /* 224 */
  {    36,     26,      0, }, /* 225 */
  {    47,     10,      0, }, /* 226 */
  {    47,      7,      0, }, /* 227 */
  {    47,     12,      0, }, /* 228 */
  {    47,     21,      0, }, /* 229 */
  {    56,      7,      0, }, /* 230 */
  {    56,     12,      0, }, /* 231 */
  {    56,      6,      0, }, /* 232 */
  {    56,     21,      0, }, /* 233 */
  {    56,     13,      0, }, /* 234 */
  {    32,      7,      0, }, /* 235 */
  {    32,     12,      0, }, /* 236 */
  {    32,      6,      0, }, /* 237 */
  {    32,     13,      0, }, /* 238 */
  {    57,      7,      0, }, /* 239 */
  {    57,     26,      0, }, /* 240 */
  {    57,     21,      0, }, /* 241 */
  {    57,     12,      0, }, /* 242 */
  {    57,     13,      0, }, /* 243 */
  {    57,     15,      0, }, /* 244 */
  {    57,     22,      0, }, /* 245 */
  {    57,     18,      0, }, /* 246 */
  {    57,     10,      0, }, /* 247 */
  {    38,      7,      0, }, /* 248 */
  {    38,     10,      0, }, /* 249 */
  {    38,     12,      0, }, /* 250 */
  {    38,     13,      0, }, /* 251 */
  {    38,     21,      0, }, /* 252 */
  {    38,     26,      0, }, /* 253 */
  {    16,      9,   7264, }, /* 254 */
  {    16,      7,      0, }, /* 255 */
  {    16,      6,      0, }, /* 256 */
  {    23,      7,      0, }, /* 257 */
  {    15,      7,      0, }, /* 258 */
  {    15,     12,      0, }, /* 259 */
  {    15,     21,      0, }, /* 260 */
  {    15,     15,      0, }, /* 261 */
  {    15,     26,      0, }, /* 262 */
  {     8,      7,      0, }, /* 263 */
  {     7,     17,      0, }, /* 264 */
  {     7,      7,      0, }, /* 265 */
  {     7,     21,      0, }, /* 266 */
  {    40,     29,      0, }, /* 267 */
  {    40,      7,      0, }, /* 268 */
  {    40,     22,      0, }, /* 269 */
  {    40,     18,      0, }, /* 270 */
  {    45,      7,      0, }, /* 271 */
  {    45,     14,      0, }, /* 272 */
  {    50,      7,      0, }, /* 273 */
  {    50,     12,      0, }, /* 274 */
  {    24,      7,      0, }, /* 275 */
  {    24,     12,      0, }, /* 276 */
  {     6,      7,      0, }, /* 277 */
  {     6,     12,      0, }, /* 278 */
  {    51,      7,      0, }, /* 279 */
  {    51,     12,      0, }, /* 280 */
  {    31,      7,      0, }, /* 281 */
  {    31,     12,      0, }, /* 282 */
  {    31,     10,      0, }, /* 283 */
  {    31,     21,      0, }, /* 284 */
  {    31,      6,      0, }, /* 285 */
  {    31,     23,      0, }, /* 286 */
  {    31,     13,      0, }, /* 287 */
  {    31,     15,      0, }, /* 288 */
  {    37,     21,      0, }, /* 289 */
  {    37,     17,      0, }, /* 290 */
  {    37,     12,      0, }, /* 291 */
  {    37,     29,      0, }, /* 292 */
  {    37,     13,      0, }, /* 293 */
  {    37,      7,      0, }, /* 294 */
  {    37,      6,      0, }, /* 295 */
  {    34,      7,      0, }, /* 296 */
  {    34,     12,      0, }, /* 297 */
  {    34,     10,      0, }, /* 298 */
  {    34,     26,      0, }, /* 299 */
  {    34,     21,      0, }, /* 300 */
  {    34,     13,      0, }, /* 301 */
  {    52,      7,      0, }, /* 302 */
  {    39,      7,      0, }, /* 303 */
  {    39,     10,      0, }, /* 304 */
  {    39,     13,      0, }, /* 305 */
  {    39,     15,      0, }, /* 306 */
  {    39,     26,      0, }, /* 307 */
  {    31,     26,      0, }, /* 308 */
  {     5,      7,      0, }, /* 309 */
  {     5,     12,      0, }, /* 310 */
  {     5,     10,      0, }, /* 311 */
  {     5,     21,      0, }, /* 312 */
  {    90,      7,      0, }, /* 313 */
  {    90,     10,      0, }, /* 314 */
  {    90,     12,      0, }, /* 315 */
  {    90,     13,      0, }, /* 316 */
  {    90,     21,      0, }, /* 317 */
  {    90,      6,      0, }, /* 318 */
  {    61,     12,      0, }, /* 319 */
  {    61,     10,      0, }, /* 320 */
  {    61,      7,      0, }, /* 321 */
  {    61,     13,      0, }, /* 322 */
  {    61,     21,      0, }, /* 323 */
  {    61,     26,      0, }, /* 324 */
  {    75,     12,      0, }, /* 325 */
  {    75,     10,      0, }, /* 326 */
  {    75,      7,      0, }, /* 327 */
  {    75,     13,      0, }, /* 328 */
  {    92,      7,      0, }, /* 329 */
  {    92,     12,      0, }, /* 330 */
  {    92,     10,      0, }, /* 331 */
  {    92,     21,      0, }, /* 332 */
  {    69,      7,      0, }, /* 333 */
  {    69,     10,      0, }, /* 334 */
  {    69,     12,      0, }, /* 335 */
  {    69,     21,      0, }, /* 336 */
  {    69,     13,      0, }, /* 337 */
  {    72,     13,      0, }, /* 338 */
  {    72,      7,      0, }, /* 339 */
  {    72,      6,      0, }, /* 340 */
  {    72,     21,      0, }, /* 341 */
  {    75,     21,      0, }, /* 342 */
  {     9,     10,      0, }, /* 343 */
  {     9,      7,      0, }, /* 344 */
  {    12,      5,      0, }, /* 345 */
  {    12,      6,      0, }, /* 346 */
  {    33,      5,  35332, }, /* 347 */
  {    33,      5,   3814, }, /* 348 */
  {    33,      5,    -59, }, /* 349 */
  {    33,      9,  -7615, }, /* 350 */
  {    19,      5,      8, }, /* 351 */
  {    19,      9,     -8, }, /* 352 */
  {    19,      5,     74, }, /* 353 */
  {    19,      5,     86, }, /* 354 */
  {    19,      5,    100, }, /* 355 */
  {    19,      5,    128, }, /* 356 */
  {    19,      5,    112, }, /* 357 */
  {    19,      5,    126, }, /* 358 */
  {    19,      8,     -8, }, /* 359 */
  {    19,      5,      9, }, /* 360 */
  {    19,      9,    -74, }, /* 361 */
  {    19,      8,     -9, }, /* 362 */
  {    19,      5,  -7205, }, /* 363 */
  {    19,      9,    -86, }, /* 364 */
  {    19,      9,   -100, }, /* 365 */
  {    19,      9,   -112, }, /* 366 */
  {    19,      9,   -128, }, /* 367 */
  {    19,      9,   -126, }, /* 368 */
  {    27,      1,      0, }, /* 369 */
  {     9,     27,      0, }, /* 370 */
  {     9,     28,      0, }, /* 371 */
  {    27,     11,      0, }, /* 372 */
  {     9,      9,      0, }, /* 373 */
  {     9,      5,      0, }, /* 374 */
  {    19,      9,  -7517, }, /* 375 */
  {    33,      9,  -8383, }, /* 376 */
  {    33,      9,  -8262, }, /* 377 */
  {    33,      9,     28, }, /* 378 */
  {    33,      5,    -28, }, /* 379 */
  {    33,     14,     16, }, /* 380 */
  {    33,     14,    -16, }, /* 381 */
  {    33,     14,      0, }, /* 382 */
  {     9,     26,     26, }, /* 383 */
  {     9,     26,    -26, }, /* 384 */
  {     4,     26,      0, }, /* 385 */
  {    17,      9,     48, }, /* 386 */
  {    17,      5,    -48, }, /* 387 */
  {    33,      9, -10743, }, /* 388 */
  {    33,      9,  -3814, }, /* 389 */
  {    33,      9, -10727, }, /* 390 */
  {    33,      5, -10795, }, /* 391 */
  {    33,      5, -10792, }, /* 392 */
  {    33,      9, -10780, }, /* 393 */
  {    33,      9, -10749, }, /* 394 */
  {    33,      9, -10783, }, /* 395 */
  {    33,      9, -10782, }, /* 396 */
  {    33,      9, -10815, }, /* 397 */
  {    10,      5,      0, }, /* 398 */
  {    10,     26,      0, }, /* 399 */
  {    10,     12,      0, }, /* 400 */
  {    10,     21,      0, }, /* 401 */
  {    10,     15,      0, }, /* 402 */
  {    16,      5,  -7264, }, /* 403 */
  {    58,      7,      0, }, /* 404 */
  {    58,      6,      0, }, /* 405 */
  {    58,     21,      0, }, /* 406 */
  {    58,     12,      0, }, /* 407 */
  {    22,     26,      0, }, /* 408 */
  {    22,      6,      0, }, /* 409 */
  {    22,     14,      0, }, /* 410 */
  {    23,     10,      0, }, /* 411 */
  {    26,      7,      0, }, /* 412 */
  {    26,      6,      0, }, /* 413 */
  {    29,      7,      0, }, /* 414 */
  {    29,      6,      0, }, /* 415 */
  {     3,      7,      0, }, /* 416 */
  {    23,     26,      0, }, /* 417 */
  {    29,     26,      0, }, /* 418 */
  {    22,      7,      0, }, /* 419 */
  {    60,      7,      0, }, /* 420 */
  {    60,      6,      0, }, /* 421 */
  {    60,     26,      0, }, /* 422 */
  {    85,      7,      0, }, /* 423 */
  {    85,      6,      0, }, /* 424 */
  {    85,     21,      0, }, /* 425 */
  {    76,      7,      0, }, /* 426 */
  {    76,      6,      0, }, /* 427 */
  {    76,     21,      0, }, /* 428 */
  {    76,     13,      0, }, /* 429 */
  {    12,      7,      0, }, /* 430 */
  {    12,     21,      0, }, /* 431 */
  {    78,      7,      0, }, /* 432 */
  {    78,     14,      0, }, /* 433 */
  {    78,     12,      0, }, /* 434 */
  {    78,     21,      0, }, /* 435 */
  {    33,      9, -35332, }, /* 436 */
  {    33,      9, -42280, }, /* 437 */
  {    33,      9, -42308, }, /* 438 */
  {    48,      7,      0, }, /* 439 */
  {    48,     12,      0, }, /* 440 */
  {    48,     10,      0, }, /* 441 */
  {    48,     26,      0, }, /* 442 */
  {    64,      7,      0, }, /* 443 */
  {    64,     21,      0, }, /* 444 */
  {    74,     10,      0, }, /* 445 */
  {    74,      7,      0, }, /* 446 */
  {    74,     12,      0, }, /* 447 */
  {    74,     21,      0, }, /* 448 */
  {    74,     13,      0, }, /* 449 */
  {    68,     13,      0, }, /* 450 */
  {    68,      7,      0, }, /* 451 */
  {    68,     12,      0, }, /* 452 */
  {    68,     21,      0, }, /* 453 */
  {    73,      7,      0, }, /* 454 */
  {    73,     12,      0, }, /* 455 */
  {    73,     10,      0, }, /* 456 */
  {    73,     21,      0, }, /* 457 */
  {    83,     12,      0, }, /* 458 */
  {    83,     10,      0, }, /* 459 */
  {    83,      7,      0, }, /* 460 */
  {    83,     21,      0, }, /* 461 */
  {    83,      6,      0, }, /* 462 */
  {    83,     13,      0, }, /* 463 */
  {    67,      7,      0, }, /* 464 */
  {    67,     12,      0, }, /* 465 */
  {    67,     10,      0, }, /* 466 */
  {    67,     13,      0, }, /* 467 */
  {    67,     21,      0, }, /* 468 */
  {    38,      6,      0, }, /* 469 */
  {    91,      7,      0, }, /* 470 */
  {    91,     12,      0, }, /* 471 */
  {    91,      6,      0, }, /* 472 */
  {    91,     21,      0, }, /* 473 */
  {    86,      7,      0, }, /* 474 */
  {    86,     10,      0, }, /* 475 */
  {    86,     12,      0, }, /* 476 */
  {    86,     21,      0, }, /* 477 */
  {    86,      6,      0, }, /* 478 */
  {    86,     13,      0, }, /* 479 */
  {     9,      4,      0, }, /* 480 */
  {     9,      3,      0, }, /* 481 */
  {    25,     25,      0, }, /* 482 */
  {     0,     24,      0, }, /* 483 */
  {    35,      7,      0, }, /* 484 */
  {    19,     14,      0, }, /* 485 */
  {    19,     15,      0, }, /* 486 */
  {    19,     26,      0, }, /* 487 */
  {    70,      7,      0, }, /* 488 */
  {    66,      7,      0, }, /* 489 */
  {    41,      7,      0, }, /* 490 */
  {    41,     15,      0, }, /* 491 */
  {    18,      7,      0, }, /* 492 */
  {    18,     14,      0, }, /* 493 */
  {    59,      7,      0, }, /* 494 */
  {    59,     21,      0, }, /* 495 */
  {    42,      7,      0, }, /* 496 */
  {    42,     21,      0, }, /* 497 */
  {    42,     14,      0, }, /* 498 */
  {    13,      9,     40, }, /* 499 */
  {    13,      5,    -40, }, /* 500 */
  {    46,      7,      0, }, /* 501 */
  {    44,      7,      0, }, /* 502 */
  {    44,     13,      0, }, /* 503 */
  {    11,      7,      0, }, /* 504 */
  {    80,      7,      0, }, /* 505 */
  {    80,     21,      0, }, /* 506 */
  {    80,     15,      0, }, /* 507 */
  {    65,      7,      0, }, /* 508 */
  {    65,     15,      0, }, /* 509 */
  {    65,     21,      0, }, /* 510 */
  {    71,      7,      0, }, /* 511 */
  {    71,     21,      0, }, /* 512 */
  {    97,      7,      0, }, /* 513 */
  {    96,      7,      0, }, /* 514 */
  {    30,      7,      0, }, /* 515 */
  {    30,     12,      0, }, /* 516 */
  {    30,     15,      0, }, /* 517 */
  {    30,     21,      0, }, /* 518 */
  {    87,      7,      0, }, /* 519 */
  {    87,     15,      0, }, /* 520 */
  {    87,     21,      0, }, /* 521 */
  {    77,      7,      0, }, /* 522 */
  {    77,     21,      0, }, /* 523 */
  {    82,      7,      0, }, /* 524 */
  {    82,     15,      0, }, /* 525 */
  {    81,      7,      0, }, /* 526 */
  {    81,     15,      0, }, /* 527 */
  {    88,      7,      0, }, /* 528 */
  {     0,     15,      0, }, /* 529 */
  {    93,     10,      0, }, /* 530 */
  {    93,     12,      0, }, /* 531 */
  {    93,      7,      0, }, /* 532 */
  {    93,     21,      0, }, /* 533 */
  {    93,     15,      0, }, /* 534 */
  {    93,     13,      0, }, /* 535 */
  {    84,     12,      0, }, /* 536 */
  {    84,     10,      0, }, /* 537 */
  {    84,      7,      0, }, /* 538 */
  {    84,     21,      0, }, /* 539 */
  {    84,      1,      0, }, /* 540 */
  {   100,      7,      0, }, /* 541 */
  {   100,     13,      0, }, /* 542 */
  {    95,     12,      0, }, /* 543 */
  {    95,      7,      0, }, /* 544 */
  {    95,     10,      0, }, /* 545 */
  {    95,     13,      0, }, /* 546 */
  {    95,     21,      0, }, /* 547 */
  {    99,     12,      0, }, /* 548 */
  {    99,     10,      0, }, /* 549 */
  {    99,      7,      0, }, /* 550 */
  {    99,     21,      0, }, /* 551 */
  {    99,     13,      0, }, /* 552 */
  {   101,      7,      0, }, /* 553 */
  {   101,     12,      0, }, /* 554 */
  {   101,     10,      0, }, /* 555 */
  {   101,     13,      0, }, /* 556 */
  {    62,      7,      0, }, /* 557 */
  {    62,     14,      0, }, /* 558 */
  {    62,     21,      0, }, /* 559 */
  {    79,      7,      0, }, /* 560 */
  {    98,      7,      0, }, /* 561 */
  {    98,     10,      0, }, /* 562 */
  {    98,     12,      0, }, /* 563 */
  {    98,      6,      0, }, /* 564 */
  {    19,     12,      0, }, /* 565 */
  {    26,     26,      0, }, /* 566 */
};

const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* U+0000 */
 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */
 32, 33, 34, 34, 35, 36, 37, 38, 39, 40, 40, 40, 41, 42, 43, 44, /* U+1000 */
 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, /* U+1800 */
 61, 62, 63, 64, 65, 65, 66, 67, 68, 69, 70, 71, 72, 70, 73, 74, /* U+2000 */
 75, 75, 65, 76, 65, 65, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, /* U+2800 */
 87, 88, 89, 90, 91, 92, 93, 70, 94, 94, 94, 94, 94, 94, 94, 94, /* U+3000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+3800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+4000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 94, 94, 94, 94, /* U+4800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+5000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+5800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+6000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+6800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+7000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+7800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+8000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+8800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+9000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 96, /* U+9800 */
 97, 98, 98, 98, 98, 98, 98, 98, 98, 99,100,100,101,102,103,104, /* U+A000 */
105,106,107,108,109,110,111,112, 34, 34, 34, 34, 34, 34, 34, 34, /* U+A800 */
 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+B000 */
 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+B800 */
 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+C000 */
 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+C800 */
 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,113, /* U+D000 */
114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+D800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+E000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+E800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F000 */
115,115, 94, 94,116,117,118,119,120,120,121,122,123,124,125,126, /* U+F800 */
127,128,129,130, 78,131,132,133,134,135, 78, 78, 78, 78, 78, 78, /* U+10000 */
136, 78,137,138,139, 78,140, 78,141, 78, 78, 78,142, 78, 78, 78, /* U+10800 */
143,144,145,146, 78, 78, 78, 78, 78, 78, 78, 78, 78,147, 78, 78, /* U+11000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+11800 */
148,148,148,148,148,148,149, 78,150, 78, 78, 78, 78, 78, 78, 78, /* U+12000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+12800 */
151,151,151,151,151,151,151,151,152, 78, 78, 78, 78, 78, 78, 78, /* U+13000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+13800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+14000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+14800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+15000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+15800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+16000 */
153,153,153,153,154, 78, 78, 78, 78, 78, 78, 78, 78, 78,155,156, /* U+16800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+17000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+17800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+18000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+18800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+19000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+19800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1A800 */
157, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1C800 */
 70,158,159,160,161, 78,162, 78,163,164,165,166,167,168,169,170, /* U+1D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,171,172, 78, 78, /* U+1E800 */
173,174,175,176,177, 78,178,179,180,181,182,183,184,185,186, 78, /* U+1F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+1F800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+20000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+20800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+21000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+21800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+22000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+22800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+23000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+23800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+24000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+24800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+25000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+25800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+26000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+26800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+27000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+27800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+28000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+28800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+29000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+29800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,187, 94, 94, /* U+2A000 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+2A800 */
 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,188, 94, /* U+2B000 */
189, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2F000 */
 94, 94, 94, 94,189, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+2F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+30000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+30800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+31000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+31800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+32000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+32800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+33000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+33800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+34000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+34800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+35000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+35800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+36000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+36800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+37000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+37800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+38000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+38800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+39000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+39800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+3F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+40000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+40800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+41000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+41800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+42000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+42800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+43000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+43800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+44000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+44800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+45000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+45800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+46000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+46800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+47000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+47800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+48000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+48800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+49000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+49800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+4F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+50000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+50800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+51000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+51800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+52000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+52800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+53000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+53800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+54000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+54800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+55000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+55800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+56000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+56800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+57000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+57800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+58000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+58800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+59000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+59800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+5F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+60000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+60800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+61000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+61800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+62000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+62800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+63000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+63800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+64000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+64800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+65000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+65800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+66000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+66800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+67000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+67800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+68000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+68800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+69000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+69800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+6F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+70000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+70800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+71000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+71800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+72000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+72800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+73000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+73800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+74000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+74800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+75000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+75800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+76000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+76800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+77000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+77800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+78000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+78800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+79000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+79800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+7F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+80000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+80800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+81000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+81800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+82000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+82800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+83000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+83800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+84000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+84800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+85000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+85800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+86000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+86800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+87000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+87800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+88000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+88800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+89000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+89800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+8F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+90000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+90800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+91000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+91800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+92000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+92800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+93000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+93800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+94000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+94800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+95000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+95800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+96000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+96800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+97000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+97800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+98000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+98800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+99000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+99800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9A000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9A800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9B000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9B800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9C000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9C800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9D000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9D800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9E000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9E800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9F000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+9F800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A0000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A0800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A1000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A1800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A2000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A2800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A3000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A3800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A4000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A4800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A5000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A5800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A6000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A6800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A7000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A7800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A8000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A8800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A9000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+A9800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AA000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AA800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AB000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AB800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AC000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AC800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AD000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AD800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AE000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AE800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AF000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+AF800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B0000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B0800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B1000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B1800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B2000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B2800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B3000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B3800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B4000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B4800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B5000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B5800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B6000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B6800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B7000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B7800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B8000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B8800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B9000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+B9800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BA000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BA800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BB000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BB800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BC000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BC800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BD000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BD800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BE000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BE800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BF000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+BF800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C0000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C0800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C1000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C1800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C2000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C2800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C3000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C3800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C4000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C4800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C5000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C5800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C6000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C6800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C7000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C7800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C8000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C8800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C9000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+C9800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CA000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CA800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CB000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CB800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CC000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CC800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CD000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CD800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CE000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CE800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CF000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+CF800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D0000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D0800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D1000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D1800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D2000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D2800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D3000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D3800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D4000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D4800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D5000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D5800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D6000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D6800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D7000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D7800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D8000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D8800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D9000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+D9800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DA000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DA800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DB000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DB800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DC000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DC800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DD000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DD800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DE000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DE800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DF000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+DF800 */
190, 78,191,192, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E0000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E0800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E1000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E1800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E2000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E2800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E3000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E3800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E4000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E4800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E5000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E5800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E6000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E6800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E7000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E7800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E8000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E8800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E9000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+E9800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EA000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EA800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EB000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EB800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EC000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EC800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+ED000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+ED800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EE000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EE800 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EF000 */
 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, /* U+EF800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F0000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F0800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F1000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F1800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F2000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F2800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F3000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F3800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F4000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F4800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F5000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F5800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F6000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F6800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F7000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F7800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F8000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F8800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F9000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+F9800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FA000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FA800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FB000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FB800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FC000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FC800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FD000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FD800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FE000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FE800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+FF000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,193, /* U+FF800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+100000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+100800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+101000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+101800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+102000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+102800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+103000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+103800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+104000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+104800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+105000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+105800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+106000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+106800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+107000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+107800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+108000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+108800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+109000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+109800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10A000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10A800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10B000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10B800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10C000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10C800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10D000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10D800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10E000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10E800 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* U+10F000 */
115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,193, /* U+10F800 */
};

const pcre_uint16 PRIV(ucd_stage2)[] = { /* 49664 bytes, block = 128 */
/* block 0 */
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  1,  2,  2,  2,  3,  2,  2,  2,  4,  5,  2,  6,  2,  7,  2,  2,
  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  6,  6,  6,  2,
  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  4,  2,  5, 10, 11,
 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  4,  6,  5,  6,  0,

/* block 1 */
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  1,  2,  3,  3,  3,  3, 13,  2, 10, 13, 14, 15,  6, 16, 13, 10,
 13,  6, 17, 17, 10, 18,  2,  2, 10, 17, 14, 19, 17, 17, 17,  2,
  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
  9,  9,  9,  9,  9,  9,  9,  6,  9,  9,  9,  9,  9,  9,  9, 20,
 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
 12, 12, 12, 12, 12, 12, 12,  6, 12, 12, 12, 12, 12, 12, 12, 21,

/* block 2 */
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 24, 25, 22, 23, 22, 23, 22, 23, 20, 22, 23, 22, 23, 22, 23, 22,
 23, 22, 23, 22, 23, 22, 23, 22, 23, 20, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 26, 22, 23, 22, 23, 22, 23, 27,

/* block 3 */
 28, 29, 22, 23, 22, 23, 30, 22, 23, 31, 31, 22, 23, 20, 32, 33,
 34, 22, 23, 31, 35, 36, 37, 38, 22, 23, 39, 20, 37, 40, 41, 42,
 22, 23, 22, 23, 22, 23, 43, 22, 23, 43, 20, 20, 22, 23, 43, 22,
 23, 44, 44, 22, 23, 22, 23, 45, 22, 23, 20, 14, 22, 23, 20, 46,
 14, 14, 14, 14, 47, 48, 49, 47, 48, 49, 47, 48, 49, 22, 23, 22,
 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 50, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 20, 47, 48, 49, 22, 23, 51, 52, 22, 23, 22, 23, 22, 23, 22, 23,

/* block 4 */
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 53, 20, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 20, 20, 20, 20, 20, 20, 54, 22, 23, 55, 56, 57,
 57, 22, 23, 58, 59, 60, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 61, 62, 63, 64, 65, 20, 66, 66, 20, 67, 20, 68, 20, 20, 20, 20,
 66, 20, 20, 69, 20, 70, 71, 20, 72, 73, 20, 74, 20, 20, 20, 73,
 20, 75, 76, 20, 20, 77, 20, 20, 20, 20, 20, 20, 20, 78, 20, 20,

/* block 5 */
 79, 20, 20, 79, 20, 20, 20, 20, 79, 80, 81, 81, 82, 20, 20, 20,
 20, 20, 83, 20, 14, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85,
 85, 85, 10, 10, 10, 10, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
 85, 85, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 84, 84, 84, 84, 84, 10, 10, 10, 10, 10, 86, 86, 85, 10, 85, 10,
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,

/* block 6 */
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 89, 90, 89, 90, 85, 91, 89, 90, 92, 92, 93, 94, 94, 94,  2, 92,

/* block 7 */
 92, 92, 92, 92, 91, 10, 95,  2, 96, 96, 96, 92, 97, 92, 98, 98,
 99,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
100,100, 92,100,100,100,100,100,100,100,100,100,101,102,102,102,
 99,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
103,103,104,103,103,103,103,103,103,103,103,103,105,106,106,107,
108,109,110,110,110,111,112,113, 89, 90, 89, 90, 89, 90, 89, 90,
 89, 90,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
116,117,118, 99,119,120,121, 89, 90,122, 89, 90, 99,123,123,123,

/* block 8 */
124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,

/* block 9 */
128,129,130,131,131, 87, 87,131,132,132,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
133,128,129,128,129,128,129,128,129,128,129,128,129,128,129,134,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,

/* block 10 */
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129, 92, 92, 92, 92, 92, 92, 92, 92,
 92,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
135,135,135,135,135,135,135, 92, 92,136,137,137,137,137,137,137,
 92,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,

/* block 11 */
138,138,138,138,138,138,138,139, 92,  2,140, 92, 92, 92, 92,141,
 92,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
142,142,142,142,142,142,142,142,142,142,142,142,142,142,143,142,
144,142,142,144,142,142,144,142, 92, 92, 92, 92, 92, 92, 92, 92,
145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
145,145,145,145,145,145,145,145,145,145,145, 92, 92, 92, 92, 92,
145,145,145,144,144, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 12 */
146,146,146,146,146, 92,147,147,147,148,148,149,  2,148,150,150,
151,151,151,151,151,151,151,151,151,151,151,  2, 92, 92,148,  2,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
 85,152,152,152,152,152,152,152,152,152,152, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87,151,151,151,151,151,151,151,151,151, 87,
  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,148,148,148,148,152,152,
 87,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,

/* block 13 */
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,148,152,151,151,151,151,151,151,151, 16,150,151,
151,151,151,151,151,153,153,151,151,150,151,151,151,151,152,152,
154,154,154,154,154,154,154,154,154,154,152,152,152,150,150,152,

/* block 14 */
155,155,155,155,155,155,155,155,155,155,155,155,155,155, 92,156,
157,158,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
158,158,158,158,158,158,158,158,158,158,158, 92, 92,157,157,157,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,

/* block 15 */
159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160,
160,159, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
161,161,161,161,161,161,161,161,161,161,162,162,162,162,162,162,
162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
162,162,162,162,162,162,162,162,162,162,162,163,163,163,163,163,
163,163,163,163,164,164,165,166,166,166,164, 92, 92, 92, 92, 92,

/* block 16 */
167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
167,167,167,167,167,167,168,168,168,168,169,168,168,168,168,168,
168,168,168,168,169,168,168,168,169,168,168,168,168,168, 92, 92,
170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, 92,
171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
171,171,171,171,171,171,171,171,171,172,172,172, 92, 92,173, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 17 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
152, 92,152,152,152,152,152,152,152,152,152,152,152, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92,151,151,151,151,151,151,151,151,151,151,151,151,
151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, 92,

/* block 18 */
174,174,174,175,176,176,176,176,176,176,176,176,176,176,176,176,
176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
176,176,176,176,176,176,176,176,176,176,174,175,174,176,175,175,
175,174,174,174,174,174,174,174,174,175,175,175,175,174,175,175,
176, 87, 87,174,174,174,174,174,176,176,176,176,176,176,176,176,
176,176,174,174,  2,  2,177,177,177,177,177,177,177,177,177,177,
178,179,176,176,176,176,176,176, 92,176,176,176,176,176,176,176,

/* block 19 */
 92,180,181,181, 92,182,182,182,182,182,182,182,182, 92, 92,182,
182, 92, 92,182,182,182,182,182,182,182,182,182,182,182,182,182,
182,182,182,182,182,182,182,182,182, 92,182,182,182,182,182,182,
182, 92,182, 92, 92, 92,182,182,182,182, 92, 92,180,182,181,181,
181,180,180,180,180, 92, 92,181,181, 92, 92,181,181,180,182, 92,
 92, 92, 92, 92, 92, 92, 92,181, 92, 92, 92, 92,182,182, 92,182,
182,182,180,180, 92, 92,183,183,183,183,183,183,183,183,183,183,
182,182,184,184,185,185,185,185,185,185,186,184, 92, 92, 92, 92,

/* block 20 */
 92,187,187,188, 92,189,189,189,189,189,189, 92, 92, 92, 92,189,
189, 92, 92,189,189,189,189,189,189,189,189,189,189,189,189,189,
189,189,189,189,189,189,189,189,189, 92,189,189,189,189,189,189,
189, 92,189,189, 92,189,189, 92,189,189, 92, 92,187, 92,188,188,
188,187,187, 92, 92, 92, 92,187,187, 92, 92,187,187,187, 92, 92,
 92,187, 92, 92, 92, 92, 92, 92, 92,189,189,189,189, 92,189, 92,
 92, 92, 92, 92, 92, 92,190,190,190,190,190,190,190,190,190,190,
187,187,189,189,189,187, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 21 */
 92,191,191,192, 92,193,193,193,193,193,193,193,193,193, 92,193,
193,193, 92,193,193,193,193,193,193,193,193,193,193,193,193,193,
193,193,193,193,193,193,193,193,193, 92,193,193,193,193,193,193,
193, 92,193,193, 92,193,193,193,193,193, 92, 92,191,193,192,192,
192,191,191,191,191,191, 92,191,191,192, 92,192,192,191, 92, 92,
193, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
193,193,191,191, 92, 92,194,194,194,194,194,194,194,194,194,194,
195,196, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 22 */
 92,197,198,198, 92,199,199,199,199,199,199,199,199, 92, 92,199,
199, 92, 92,199,199,199,199,199,199,199,199,199,199,199,199,199,
199,199,199,199,199,199,199,199,199, 92,199,199,199,199,199,199,
199, 92,199,199, 92,199,199,199,199,199, 92, 92,197,199,198,197,
198,197,197,197,197, 92, 92,198,198, 92, 92,198,198,197, 92, 92,
 92, 92, 92, 92, 92, 92,197,198, 92, 92, 92, 92,199,199, 92,199,
199,199,197,197, 92, 92,200,200,200,200,200,200,200,200,200,200,
201,199,202,202,202,202,202,202, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 23 */
 92, 92,203,204, 92,204,204,204,204,204,204, 92, 92, 92,204,204,
204, 92,204,204,204,204, 92, 92, 92,204,204, 92,204, 92,204,204,
 92, 92, 92,204,204, 92, 92, 92,204,204,204, 92, 92, 92,204,204,
204,204,204,204,204,204,204,204,204,204, 92, 92, 92, 92,205,205,
203,205,205, 92, 92, 92,205,205,205, 92,205,205,205,203, 92, 92,
204, 92, 92, 92, 92, 92, 92,205, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92,206,206,206,206,206,206,206,206,206,206,
207,207,207,208,208,208,208,208,208,209,208, 92, 92, 92, 92, 92,

/* block 24 */
 92,210,210,210, 92,211,211,211,211,211,211,211,211, 92,211,211,
211, 92,211,211,211,211,211,211,211,211,211,211,211,211,211,211,
211,211,211,211,211,211,211,211,211, 92,211,211,211,211,211,211,
211,211,211,211, 92,211,211,211,211,211, 92, 92, 92,211,212,212,
212,210,210,210,210, 92,212,212,212, 92,212,212,212,212, 92, 92,
 92, 92, 92, 92, 92,212,212, 92,211,211, 92, 92, 92, 92, 92, 92,
211,211,212,212, 92, 92,213,213,213,213,213,213,213,213,213,213,
 92, 92, 92, 92, 92, 92, 92, 92,214,214,214,214,214,214,214,215,

/* block 25 */
 92, 92,216,216, 92,217,217,217,217,217,217,217,217, 92,217,217,
217, 92,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
217,217,217,217,217,217,217,217,217, 92,217,217,217,217,217,217,
217,217,217,217, 92,217,217,217,217,217, 92, 92,218,217,216,218,
216,216,216,216,216, 92,218,216,216, 92,216,216,218,218, 92, 92,
 92, 92, 92, 92, 92,216,216, 92, 92, 92, 92, 92, 92, 92,217, 92,
217,217,218,218, 92, 92,219,219,219,219,219,219,219,219,219,219,
 92,217,217, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 26 */
 92, 92,220,220, 92,221,221,221,221,221,221,221,221, 92,221,221,
221, 92,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
221,221,221,221,221,221,221,221,221,221,221, 92, 92,221,220,220,
220,222,222,222,222, 92,220,220,220, 92,220,220,220,222,221, 92,
 92, 92, 92, 92, 92, 92, 92,220, 92, 92, 92, 92, 92, 92, 92, 92,
221,221,222,222, 92, 92,223,223,223,223,223,223,223,223,223,223,
224,224,224,224,224,224, 92, 92, 92,225,221,221,221,221,221,221,

/* block 27 */
 92, 92,226,226, 92,227,227,227,227,227,227,227,227,227,227,227,
227,227,227,227,227,227,227, 92, 92, 92,227,227,227,227,227,227,
227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,
227,227, 92,227,227,227,227,227,227,227,227,227, 92,227, 92, 92,
227,227,227,227,227,227,227, 92, 92, 92,228, 92, 92, 92, 92,226,
226,226,228,228,228, 92,228, 92,226,226,226,226,226,226,226,226,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92,226,226,229, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 28 */
 92,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
230,231,230,230,231,231,231,231,231,231,231, 92, 92, 92, 92,  3,
230,230,230,230,230,230,232,231,231,231,231,231,231,231,231,233,
234,234,234,234,234,234,234,234,234,234,233,233, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 29 */
 92,235,235, 92,235, 92, 92,235,235, 92,235, 92, 92,235, 92, 92,
 92, 92, 92, 92,235,235,235,235, 92,235,235,235,235,235,235,235,
 92,235,235,235, 92,235, 92,235, 92, 92,235,235, 92,235,235,235,
235,236,235,235,236,236,236,236,236,236, 92,236,236,235, 92, 92,
235,235,235,235,235, 92,237, 92,236,236,236,236,236,236, 92, 92,
238,238,238,238,238,238,238,238,238,238, 92, 92,235,235,235,235,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 30 */
239,240,240,240,241,241,241,241,241,241,241,241,241,241,241,241,
241,241,241,240,241,240,240,240,242,242,240,240,240,240,240,240,
243,243,243,243,243,243,243,243,243,243,244,244,244,244,244,244,
244,244,244,244,240,242,240,242,240,242,245,246,245,246,247,247,
239,239,239,239,239,239,239,239, 92,239,239,239,239,239,239,239,
239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,
239,239,239,239,239,239,239,239,239,239,239,239,239, 92, 92, 92,
 92,242,242,242,242,242,242,242,242,242,242,242,242,242,242,247,

/* block 31 */
242,242,242,242,242,241,242,242,239,239,239,239,239,242,242,242,
242,242,242,242,242,242,242,242, 92,242,242,242,242,242,242,242,
242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
242,242,242,242,242,242,242,242,242,242,242,242,242, 92,240,240,
240,240,240,240,240,240,242,240,240,240,240,240,240, 92,240,240,
241,241,241,241,241, 13, 13, 13, 13,241,241, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 32 */
248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
248,248,248,248,248,248,248,248,248,248,248,249,249,250,250,250,
250,249,250,250,250,250,250,250,249,250,250,249,249,250,250,248,
251,251,251,251,251,251,251,251,251,251,252,252,252,252,252,252,
248,248,248,248,248,248,249,249,250,250,248,248,248,248,250,250,
250,248,249,249,249,248,248,249,249,249,249,249,249,249,248,248,
248,250,250,250,250,248,248,248,248,248,248,248,248,248,248,248,

/* block 33 */
248,248,250,249,249,250,250,249,249,249,249,249,249,250,248,249,
251,251,251,251,251,251,251,251,251,251,249,249,249,250,253,253,
254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
254,254,254,254,254,254, 92,254, 92, 92, 92, 92, 92,254, 92, 92,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,  2,256,255,255,255,

/* block 34 */
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,

/* block 35 */
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258, 92,258,258,258,258, 92, 92,
258,258,258,258,258,258,258, 92,258, 92,258,258,258,258, 92, 92,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,

/* block 36 */
258,258,258,258,258,258,258,258,258, 92,258,258,258,258, 92, 92,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258, 92,258,258,258,258, 92, 92,258,258,258,258,258,258,258, 92,
258, 92,258,258,258,258, 92, 92,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258, 92,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,

/* block 37 */
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258, 92,258,258,258,258, 92, 92,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258,258,258,258,258, 92, 92,259,259,259,
260,260,260,260,260,260,260,260,260,261,261,261,261,261,261,261,
261,261,261,261,261,261,261,261,261,261,261,261,261, 92, 92, 92,

/* block 38 */
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
262,262,262,262,262,262,262,262,262,262, 92, 92, 92, 92, 92, 92,
263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
263,263,263,263,263, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 39 */
264,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,

/* block 40 */
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,

/* block 41 */
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,266,266,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,

/* block 42 */
267,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,
268,268,268,268,268,268,268,268,268,268,268,269,270, 92, 92, 92,
271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,
271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,
271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,
271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,
271,271,271,271,271,271,271,271,271,271,271,  2,  2,  2,272,272,
272, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 43 */
273,273,273,273,273,273,273,273,273,273,273,273,273, 92,273,273,
273,273,274,274,274, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,
275,275,276,276,276,  2,  2, 92, 92, 92, 92, 92, 92, 92, 92, 92,
277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,
277,277,278,278, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
279,279,279,279,279,279,279,279,279,279,279,279,279, 92,279,279,
279, 92,280,280, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 44 */
281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
281,281,281,281,282,282,283,282,282,282,282,282,282,282,283,283,
283,283,283,283,283,283,282,283,283,282,282,282,282,282,282,282,
282,282,282,282,284,284,284,285,284,284,284,286,281,282, 92, 92,
287,287,287,287,287,287,287,287,287,287, 92, 92, 92, 92, 92, 92,
288,288,288,288,288,288,288,288,288,288, 92, 92, 92, 92, 92, 92,

/* block 45 */
289,289,  2,  2,289,  2,290,289,289,289,289,291,291,291,292, 92,
293,293,293,293,293,293,293,293,293,293, 92, 92, 92, 92, 92, 92,
294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,295,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,294,294,294,294,294, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 46 */
294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
294,294,294,294,294,294,294,294,294,291,294, 92, 92, 92, 92, 92,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
265,265,265,265,265,265, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 47 */
296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,
296,296,296,296,296,296,296,296,296,296,296,296,296, 92, 92, 92,
297,297,297,298,298,298,298,297,297,298,298,298, 92, 92, 92, 92,
298,298,297,298,298,298,298,298,298,297,297,297, 92, 92, 92, 92,
299, 92, 92, 92,300,300,301,301,301,301,301,301,301,301,301,301,
302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
302,302,302,302,302,302,302,302,302,302,302,302,302,302, 92, 92,
302,302,302,302,302, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 48 */
303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
303,303,303,303,303,303,303,303,303,303,303,303, 92, 92, 92, 92,
304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
304,303,303,303,303,303,303,303,304,304, 92, 92, 92, 92, 92, 92,
305,305,305,305,305,305,305,305,305,305,306, 92, 92, 92,307,307,
308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,

/* block 49 */
309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,
309,309,309,309,309,309,309,310,310,311,311,311, 92, 92,312,312,
313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
313,313,313,313,313,314,315,314,315,315,315,315,315,315,315, 92,
315,314,315,314,314,315,315,315,315,315,315,315,315,314,314,314,
314,314,314,315,315,315,315,315,315,315,315,315,315, 92, 92,315,

/* block 50 */
316,316,316,316,316,316,316,316,316,316, 92, 92, 92, 92, 92, 92,
316,316,316,316,316,316,316,316,316,316, 92, 92, 92, 92, 92, 92,
317,317,317,317,317,317,317,318,317,317,317,317,317,317, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 51 */
319,319,319,319,320,321,321,321,321,321,321,321,321,321,321,321,
321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
321,321,321,321,319,320,319,319,319,319,319,320,319,320,320,320,
320,320,319,320,320,321,321,321,321,321,321,321, 92, 92, 92, 92,
322,322,322,322,322,322,322,322,322,322,323,323,323,323,323,323,
323,324,324,324,324,324,324,324,324,324,324,319,319,319,319,319,
319,319,319,319,324,324,324,324,324,324,324,324,324, 92, 92, 92,

/* block 52 */
325,325,326,327,327,327,327,327,327,327,327,327,327,327,327,327,
327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
327,326,325,325,325,325,326,326,325,325,326,325,326,326,327,327,
328,328,328,328,328,328,328,328,328,328,327,327,327,327,327,327,
329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,
329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,
329,329,329,329,329,329,330,331,330,330,331,331,331,330,331,330,
330,330,331,331, 92, 92, 92, 92, 92, 92, 92, 92,332,332,332,332,

/* block 53 */
333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
333,333,333,333,334,334,334,334,334,334,334,334,335,335,335,335,
335,335,335,335,334,334,335,335, 92, 92, 92,336,336,336,336,336,
337,337,337,337,337,337,337,337,337,337, 92, 92, 92,333,333,333,
338,338,338,338,338,338,338,338,338,338,339,339,339,339,339,339,
339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
339,339,339,339,339,339,339,339,340,340,340,340,340,340,341,341,

/* block 54 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
342,342,342,342,342,342,342,342, 92, 92, 92, 92, 92, 92, 92, 92,
 87, 87, 87,  2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87,343, 87, 87, 87, 87, 87, 87, 87,344,344,344,344, 87,344,344,
344,344,343,343, 87,344,344, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 55 */
 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
 20, 20, 20, 20, 20, 20, 99, 99, 99, 99, 99,345, 84, 84, 84, 84,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 93, 93, 93,
 93, 93, 84, 84, 84, 84, 93, 93, 93, 93, 93, 20, 20, 20, 20, 20,
 20, 20, 20, 20, 20, 20, 20, 20,346,347, 20, 20, 20,348, 20, 20,

/* block 56 */
 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 84, 84, 84, 84, 84,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 93,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 87, 87, 87, 87,

/* block 57 */
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,

/* block 58 */
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 20, 20, 20, 20, 20,349, 20, 20,350, 20,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,

/* block 59 */
351,351,351,351,351,351,351,351,352,352,352,352,352,352,352,352,
351,351,351,351,351,351, 92, 92,352,352,352,352,352,352, 92, 92,
351,351,351,351,351,351,351,351,352,352,352,352,352,352,352,352,
351,351,351,351,351,351,351,351,352,352,352,352,352,352,352,352,
351,351,351,351,351,351, 92, 92,352,352,352,352,352,352, 92, 92,
 99,351, 99,351, 99,351, 99,351, 92,352, 92,352, 92,352, 92,352,
351,351,351,351,351,351,351,351,352,352,352,352,352,352,352,352,
353,353,354,354,354,354,355,355,356,356,357,357,358,358, 92, 92,

/* block 60 */
351,351,351,351,351,351,351,351,359,359,359,359,359,359,359,359,
351,351,351,351,351,351,351,351,359,359,359,359,359,359,359,359,
351,351,351,351,351,351,351,351,359,359,359,359,359,359,359,359,
351,351, 99,360, 99, 92, 99, 99,352,352,361,361,362, 91,363, 91,
 91, 91, 99,360, 99, 92, 99, 99,364,364,364,364,362, 91, 91, 91,
351,351, 99, 99, 92, 92, 99, 99,352,352,365,365, 92, 91, 91, 91,
351,351, 99, 99, 99,118, 99, 99,352,352,366,366,122, 91, 91, 91,
 92, 92, 99,360, 99, 92, 99, 99,367,367,368,368,362, 91, 91, 92,

/* block 61 */
  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 16,369,369, 16, 16,
  7,  7,  7,  7,  7,  7,  2,  2, 15, 19,  4, 15, 15, 19,  4, 15,
  2,  2,  2,  2,  2,  2,  2,  2,370,371, 16, 16, 16, 16, 16,  1,
  2,  2,  2,  2,  2,  2,  2,  2,  2, 15, 19,  2,  2,  2,  2, 11,
 11,  2,  2,  2,  6,  4,  5,  2,  2,  2,  2,  2,  2,  2,  2,  2,
  2,  2,  6,  2, 11,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,
 16, 16, 16, 16, 16, 92, 92, 92, 92, 92, 16, 16, 16, 16, 16, 16,
 17, 84, 92, 92, 17, 17, 17, 17, 17, 17,  6,  6,  6,  4,  5, 84,

/* block 62 */
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  6,  6,  6,  4,  5, 92,
 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 92, 92, 92,
  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,372,372,372,
372, 87,372,372,372, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 63 */
 13, 13,373, 13, 13, 13, 13,373, 13, 13,374,373,373,373,374,374,
373,373,373,374, 13,373, 13, 13,  6,373,373,373,373,373, 13, 13,
 13, 13, 13, 13,373, 13,375, 13,373, 13,376,377,373,373, 13,374,
373,373,378,373,374,344,344,344,344,374, 13, 13,374,374,373,373,
  6,  6,  6,  6,  6,373,374,374,374,374, 13,  6, 13, 13,379, 13,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,
381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,

/* block 64 */
382,382,382, 22, 23,382,382,382,382, 17, 92, 92, 92, 92, 92, 92,
  6,  6,  6,  6,  6, 13, 13, 13, 13, 13,  6,  6, 13, 13, 13, 13,
  6, 13, 13,  6, 13, 13,  6, 13, 13, 13, 13, 13, 13, 13,  6, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,
 13, 13,  6, 13,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,

/* block 65 */
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,

/* block 66 */
 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  6,  6, 13, 13, 13, 13, 13, 13, 13,  4,  5, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6, 13, 13, 13,

/* block 67 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6,
  6,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 68 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,

/* block 69 */
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13,383,383,383,383,383,383,383,383,383,383,
383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
384,384,384,384,384,384,384,384,384,384, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,

/* block 70 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 71 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13,  6, 13, 13, 13, 13, 13, 13, 13, 13,
 13,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6,  6,  6,  6,  6,

/* block 72 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 73 */
 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13,  4,  5,  4,  5,  4,  5,  4,  5,
  4,  5,  4,  5,  4,  5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,

/* block 74 */
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  6,  6,  6,  6,  6,  4,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,

/* block 75 */
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,

/* block 76 */
  6,  6,  6,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,  4,
  5,  4,  5,  4,  5,  4,  5,  4,  5,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  4,  5,  4,  5,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  4,  5,  6,  6,

/* block 77 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
  6,  6,  6,  6,  6, 13, 13,  6,  6,  6,  6,  6,  6, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 78 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 79 */
386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,
386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,
386,386,386,386,386,386,386,386,386,386,386,386,386,386,386, 92,
387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
387,387,387,387,387,387,387,387,387,387,387,387,387,387,387, 92,
 22, 23,388,389,390,391,392, 22, 23, 22, 23, 22, 23,393,394,395,
396, 20, 22, 23, 20, 22, 23, 20, 20, 20, 20, 20, 84, 84,397,397,

/* block 80 */
114,115,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
114,115,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
114,115,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
114,115,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
114,115,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
114,115,114,115,114,115,114,115,114,115,114,115,114,115,114,115,
114,115,114,115,398,399,399,399,399,399,399,114,115,114,115,400,
400,400,114,115, 92, 92, 92, 92, 92,401,401,401,401,402,401,401,

/* block 81 */
403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,
403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,
403,403,403,403,403,403, 92,403, 92, 92, 92, 92, 92,403, 92, 92,
404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
404,404,404,404,404,404,404,404, 92, 92, 92, 92, 92, 92, 92,405,
406, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,407,

/* block 82 */
258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,
258,258,258,258,258,258,258, 92, 92, 92, 92, 92, 92, 92, 92, 92,
258,258,258,258,258,258,258, 92,258,258,258,258,258,258,258, 92,
258,258,258,258,258,258,258, 92,258,258,258,258,258,258,258, 92,
258,258,258,258,258,258,258, 92,258,258,258,258,258,258,258, 92,
258,258,258,258,258,258,258, 92,258,258,258,258,258,258,258, 92,
131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,

/* block 83 */
  2,  2, 15, 19, 15, 19,  2,  2,  2, 15, 19,  2, 15, 19,  2,  2,
  2,  2,  2,  2,  2,  2,  2,  7,  2,  2,  7,  2, 15, 19,  2,  2,
 15, 19,  4,  5,  4,  5,  4,  5,  4,  5,  2,  2,  2,  2,  2, 85,
  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 84 */
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408, 92,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 85 */
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,

/* block 86 */
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
408,408,408,408,408,408, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92,

/* block 87 */
  1,  2,  2,  2, 13,409,344,410,  4,  5,  4,  5,  4,  5,  4,  5,
  4,  5, 13, 13,  4,  5,  4,  5,  4,  5,  4,  5,  7,  4,  5,  5,
 13,410,410,410,410,410,410,410,410,410, 87, 87, 87, 87,411,411,
  7, 85, 85, 85, 85, 85, 13, 13,410,410,410,409,344,  2, 13, 13,
 92,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,

/* block 88 */
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,412,412,412,412,412, 92, 92, 87, 87, 10, 10,413,413,412,
  7,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,  2, 85,415,415,414,

/* block 89 */
 92, 92, 92, 92, 92,416,416,416,416,416,416,416,416,416,416,416,
416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
416,416,416,416,416,416,416,416,416,416,416,416,416,416, 92, 92,
 92,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,

/* block 90 */
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, 92,
 13, 13, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
416,416,416,416,416,416,416,416,416,416,416, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,

/* block 91 */
417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,
417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, 92,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17,
 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,
417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, 13,

/* block 92 */
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, 92,

/* block 93 */
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
418,418,418,418,418,418,418,418, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 94 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,

/* block 95 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 96 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 97 */
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,421,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,

/* block 98 */
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,

/* block 99 */
420,420,420,420,420,420,420,420,420,420,420,420,420, 92, 92, 92,
422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
422,422,422,422,422,422,422, 92, 92, 92, 92, 92, 92, 92, 92, 92,
423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,
423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,
423,423,423,423,423,423,423,423,424,424,424,424,424,424,425,425,

/* block 100 */
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,

/* block 101 */
426,426,426,426,426,426,426,426,426,426,426,426,427,428,428,428,
426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
429,429,429,429,429,429,429,429,429,429,426,426, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129,128,129,128,129,128,129,430,131,
132,132,132,431,131,131,131,131,131,131,131,131,131,131,431,346,

/* block 102 */
128,129,128,129,128,129,128,129,128,129,128,129,128,129,128,129,
128,129,128,129,128,129,128,129, 92, 92, 92, 92, 92, 92, 92,131,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,433,433,433,433,433,433,433,433,433,433,
434,434,435,435,435,435,435,435, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 103 */
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 10, 10, 85, 85, 85, 85, 85, 85, 85, 85, 85,
 10, 10, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 20, 20, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
 84, 20, 20, 20, 20, 20, 20, 20, 20, 22, 23, 22, 23,436, 22, 23,

/* block 104 */
 22, 23, 22, 23, 22, 23, 22, 23, 85, 10, 10, 22, 23,437, 20, 92,
 22, 23, 22, 23, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,438, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 84, 84, 20, 14, 14, 14, 14, 14,

/* block 105 */
439,439,440,439,439,439,440,439,439,439,439,440,439,439,439,439,
439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
439,439,439,441,441,440,440,441,442,442,442,442, 92, 92, 92, 92,
 17, 17, 17, 17, 17, 17, 13, 13,  3, 13, 92, 92, 92, 92, 92, 92,
443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,
443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,
443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,
443,443,443,443,444,444,444,444, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 106 */
445,445,446,446,446,446,446,446,446,446,446,446,446,446,446,446,
446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,
446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,
446,446,446,446,445,445,445,445,445,445,445,445,445,445,445,445,
445,445,445,445,447, 92, 92, 92, 92, 92, 92, 92, 92, 92,448,448,
449,449,449,449,449,449,449,449,449,449, 92, 92, 92, 92, 92, 92,
174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
174,174,176,176,176,176,176,176,178,178,178,176, 92, 92, 92, 92,

/* block 107 */
450,450,450,450,450,450,450,450,450,450,451,451,451,451,451,451,
451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,
451,451,451,451,451,451,452,452,452,452,452,452,452,452,453,453,
454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,
454,454,454,454,454,454,454,455,455,455,455,455,455,455,455,455,
455,455,456,456, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,457,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257, 92, 92, 92,

/* block 108 */
458,458,458,459,460,460,460,460,460,460,460,460,460,460,460,460,
460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
460,460,460,458,459,459,458,458,458,458,459,459,458,459,459,459,
459,461,461,461,461,461,461,461,461,461,461,461,461,461, 92,462,
463,463,463,463,463,463,463,463,463,463, 92, 92, 92, 92,461,461,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 109 */
464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,
464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,
464,464,464,464,464,464,464,464,464,465,465,465,465,465,465,466,
466,465,465,466,466,465,465, 92, 92, 92, 92, 92, 92, 92, 92, 92,
464,464,464,465,464,464,464,464,464,464,464,464,465,466, 92, 92,
467,467,467,467,467,467,467,467,467,467, 92, 92,468,468,468,468,
248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
469,248,248,248,248,248,248,253,253,253,248,249, 92, 92, 92, 92,

/* block 110 */
470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,
470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,
470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,
471,470,471,471,471,470,470,471,471,470,470,470,470,470,471,471,
470,471,470, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,470,470,472,473,473,
474,474,474,474,474,474,474,474,474,474,474,475,476,476,475,475,
477,477,474,478,478,475,476, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 111 */
 92,258,258,258,258,258,258, 92, 92,258,258,258,258,258,258, 92,
 92,258,258,258,258,258,258, 92, 92, 92, 92, 92, 92, 92, 92, 92,
258,258,258,258,258,258,258, 92,258,258,258,258,258,258,258, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 112 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
474,474,474,475,475,476,475,475,476,475,475,477,475,476, 92, 92,
479,479,479,479,479,479,479,479,479,479, 92, 92, 92, 92, 92, 92,

/* block 113 */
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257, 92, 92, 92, 92,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257, 92, 92, 92, 92,

/* block 114 */
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,

/* block 115 */
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,

/* block 116 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419, 92, 92,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,

/* block 117 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 118 */
 20, 20, 20, 20, 20, 20, 20, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92,139,139,139,139,139, 92, 92, 92, 92, 92,145,142,145,
145,145,145,145,145,145,145,145,145,482,145,145,145,145,145,145,
145,145,145,145,145,145,145, 92,145,145,145,145,145, 92,145, 92,
145,145, 92,145,145, 92,145,145,145,145,145,145,145,145,145,145,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,

/* block 119 */
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
483,483, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,

/* block 120 */
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,

/* block 121 */
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,  4,  5,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,

/* block 122 */
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
 92, 92,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
152,152,152,152,152,152,152,152,152,152,152,152,149, 13, 92, 92,

/* block 123 */
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
  2,  2,  2,  2,  2,  2,  2,  4,  5,  2, 92, 92, 92, 92, 92, 92,
 87, 87, 87, 87, 87, 87, 87, 92, 92, 92, 92, 92, 92, 92, 92, 92,
  2,  7,  7, 11, 11,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,  4,
  5,  4,  5,  4,  5,  2,  2,  4,  5,  2,  2,  2,  2, 11, 11, 11,
  2,  2,  2, 92,  2,  2,  2,  2,  7,  4,  5,  4,  5,  4,  5,  2,
  2,  2,  6,  7,  6,  6,  6, 92,  2,  3,  2,  2, 92, 92, 92, 92,
152,152,152,152,152, 92,152,152,152,152,152,152,152,152,152,152,

/* block 124 */
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152, 92, 92, 16,

/* block 125 */
 92,  2,  2,  2,  3,  2,  2,  2,  4,  5,  2,  6,  2,  7,  2,  2,
  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  6,  6,  6,  2,
  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  4,  2,  5, 10, 11,
 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  4,  6,  5,  6,  4,
  5,  2,  4,  5,  2,  2,414,414,414,414,414,414,414,414,414,414,
 85,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,

/* block 126 */
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,414,414,414, 85, 85,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,
257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, 92,
 92, 92,257,257,257,257,257,257, 92, 92,257,257,257,257,257,257,
 92, 92,257,257,257,257,257,257, 92, 92,257,257,257, 92, 92, 92,
  3,  3,  6, 10, 13,  3,  3, 92, 13,  6,  6,  6,  6, 13, 13, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 16, 16, 16, 13, 13, 92, 92,

/* block 127 */
484,484,484,484,484,484,484,484,484,484,484,484, 92,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484, 92,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484, 92,484,484, 92,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484, 92, 92,
484,484,484,484,484,484,484,484,484,484,484,484,484,484, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 128 */
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
484,484,484,484,484,484,484,484,484,484,484, 92, 92, 92, 92, 92,

/* block 129 */
  2,  2,  2, 92, 92, 92, 92, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 17, 17, 92, 92, 92, 13, 13, 13, 13, 13, 13, 13, 13, 13,
485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
485,485,485,485,485,486,486,486,486,487,487,487,487,487,487,487,

/* block 130 */
487,487,487,487,487,487,487,487,487,487,486, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 87, 92, 92,

/* block 131 */
488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
488,488,488,488,488,488,488,488,488,488,488,488,488, 92, 92, 92,
489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
489, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 132 */
490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,
490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, 92,
491,491,491,491, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
492,493,492,492,492,492,492,492,492,492,493, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 133 */
494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,
494,494,494,494,494,494,494,494,494,494,494,494,494,494, 92,495,
496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,
496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,
496,496,496,496, 92, 92, 92, 92,496,496,496,496,496,496,496,496,
497,498,498,498,498,498, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 134 */
499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
499,499,499,499,499,499,499,499,500,500,500,500,500,500,500,500,
500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,
500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,
501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,
501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,
501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,

/* block 135 */
502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
502,502,502,502,502,502,502,502,502,502,502,502,502,502, 92, 92,
503,503,503,503,503,503,503,503,503,503, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 136 */
504,504,504,504,504,504, 92, 92,504, 92,504,504,504,504,504,504,
504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
504,504,504,504,504,504, 92,504,504, 92, 92, 92,504, 92, 92,504,
505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
505,505,505,505,505,505, 92,506,507,507,507,507,507,507,507,507,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 137 */
508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,
508,508,508,508,508,508,509,509,509,509,509,509, 92, 92, 92,510,
511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
511,511,511,511,511,511,511,511,511,511, 92, 92, 92, 92, 92,512,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 138 */
513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
514,514,514,514,514,514,514,514, 92, 92, 92, 92, 92, 92,514,514,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 139 */
515,516,516,516, 92,516,516, 92, 92, 92, 92, 92,516,516,516,516,
515,515,515,515, 92,515,515,515, 92,515,515,515,515,515,515,515,
515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
515,515,515,515, 92, 92, 92, 92,516,516,516, 92, 92, 92, 92,516,
517,517,517,517,517,517,517,517, 92, 92, 92, 92, 92, 92, 92, 92,
518,518,518,518,518,518,518,518,518, 92, 92, 92, 92, 92, 92, 92,
519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
519,519,519,519,519,519,519,519,519,519,519,519,519,520,520,521,

/* block 140 */
522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
522,522,522,522,522,522, 92, 92, 92,523,523,523,523,523,523,523,
524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
524,524,524,524,524,524, 92, 92,525,525,525,525,525,525,525,525,
526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,
526,526,526, 92, 92, 92, 92, 92,527,527,527,527,527,527,527,527,

/* block 141 */
528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
528,528,528,528,528,528,528,528,528, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 142 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
529,529,529,529,529,529,529,529,529,529,529,529,529,529,529, 92,

/* block 143 */
530,531,530,532,532,532,532,532,532,532,532,532,532,532,532,532,
532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,
532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,
532,532,532,532,532,532,532,532,531,531,531,531,531,531,531,531,
531,531,531,531,531,531,531,533,533,533,533,533,533,533, 92, 92,
 92, 92,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
534,534,534,534,534,534,535,535,535,535,535,535,535,535,535,535,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 144 */
536,536,537,538,538,538,538,538,538,538,538,538,538,538,538,538,
538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
537,537,537,536,536,536,536,537,537,536,536,539,539,540,539,539,
539,539, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,
541,541,541,541,541,541,541,541,541, 92, 92, 92, 92, 92, 92, 92,
542,542,542,542,542,542,542,542,542,542, 92, 92, 92, 92, 92, 92,

/* block 145 */
543,543,543,544,544,544,544,544,544,544,544,544,544,544,544,544,
544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,
544,544,544,544,544,544,544,543,543,543,543,543,545,543,543,543,
543,543,543,543,543, 92,546,546,546,546,546,546,546,546,546,546,
547,547,547,547, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 146 */
548,548,549,550,550,550,550,550,550,550,550,550,550,550,550,550,
550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
550,550,550,549,549,549,548,548,548,548,548,548,548,548,548,549,
549,550,550,550,550,551,551,551,551, 92, 92, 92, 92, 92, 92, 92,
552,552,552,552,552,552,552,552,552,552, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 147 */
553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,
553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,
553,553,553,553,553,553,553,553,553,553,553,554,555,554,555,555,
554,554,554,554,554,554,555,554, 92, 92, 92, 92, 92, 92, 92, 92,
556,556,556,556,556,556,556,556,556,556, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 148 */
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,

/* block 149 */
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 150 */
558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
558,558,558, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
559,559,559,559, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 151 */
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,

/* block 152 */
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
560,560,560,560,560,560,560,560,560,560,560,560,560,560,560, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 153 */
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,

/* block 154 */
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
432,432,432,432,432,432,432,432,432, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 155 */
561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
561,561,561,561,561, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
561,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, 92,

/* block 156 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,563,
563,563,563,564,564,564,564,564,564,564,564,564,564,564,564,564,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 157 */
414,412, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 158 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 159 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 92, 92, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13,343,343, 87, 87, 87, 13, 13, 13,343,343,343,
343,343,343, 16, 16, 16, 16, 16, 16, 16, 16, 87, 87, 87, 87, 87,

/* block 160 */
 87, 87, 87, 13, 13, 87, 87, 87, 87, 87, 87, 87, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 87, 87, 87, 87, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 161 */
487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
487,487,565,565,565,487, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 162 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
 17, 17, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 163 */
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,374,374,
374,374,374,374,374, 92,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,

/* block 164 */
373,373,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,373, 92,373,373,
 92, 92,373, 92, 92,373,373, 92, 92,373,373,373,373, 92,373,373,
373,373,373,373,373,373,374,374,374,374, 92,374, 92,374,374,374,
374,374,374,374, 92,374,374,374,374,374,374,374,374,374,374,374,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,

/* block 165 */
374,374,374,374,373,373, 92,373,373,373,373, 92, 92,373,373,373,
373,373,373,373,373, 92,373,373,373,373,373,373,373, 92,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,373,373, 92,373,373,373,373, 92,
373,373,373,373,373, 92,373, 92, 92, 92,373,373,373,373,373,373,
373, 92,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,

/* block 166 */
373,373,373,373,373,373,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,

/* block 167 */
374,374,374,374,374,374,374,374,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,

/* block 168 */
373,373,373,373,373,373,373,373,373,373,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374, 92, 92,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,  6,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,  6,374,374,374,374,
374,374,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,  6,374,374,374,374,

/* block 169 */
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,  6,374,374,374,374,374,374,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,  6,374,374,374,374,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,  6,
374,374,374,374,374,374,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,  6,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,

/* block 170 */
374,374,374,374,374,374,374,374,374,  6,374,374,374,374,374,374,
373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
373,373,373,373,373,373,373,373,373,  6,374,374,374,374,374,374,
374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
374,374,374,  6,374,374,374,374,374,374,373,374, 92, 92,  8,  8,
  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,

/* block 171 */
152,152,152,152, 92,152,152,152,152,152,152,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
 92,152,152, 92,152, 92, 92,152, 92,152,152,152,152,152,152,152,
152,152,152, 92,152,152,152,152, 92,152, 92,152, 92, 92, 92, 92,
 92, 92,152, 92, 92, 92, 92,152, 92,152, 92,152, 92,152,152,152,
 92,152,152, 92,152, 92, 92,152, 92,152, 92,152, 92,152, 92,152,
 92,152,152, 92,152, 92, 92,152,152,152,152, 92,152,152,152,152,
152,152,152, 92,152,152,152,152, 92,152,152,152,152, 92,152, 92,

/* block 172 */
152,152,152,152,152,152,152,152,152,152, 92,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152, 92, 92, 92, 92,
 92,152,152,152, 92,152,152,152,152,152, 92,152,152,152,152,152,
152,152,152,152,152,152,152,152,152,152,152,152, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
147,147, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 173 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 174 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92,
 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92,
 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 175 */
 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 176 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 177 */
566, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 178 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 92, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92,

/* block 179 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 92, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 180 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92,
 13, 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

/* block 181 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 92, 13, 13, 13, 13, 92, 92, 92,

/* block 182 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 92, 92,
 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 183 */
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 13, 13, 13, 13, 13,

/* block 184 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 92, 92, 92, 92, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 185 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 186 */
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
 13, 13, 13, 13, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 187 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 188 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,

/* block 189 */
419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
419,419,419,419,419,419,419,419,419,419,419,419,419,419, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 190 */
 92, 16, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,

/* block 191 */
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,

/* block 192 */
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,

/* block 193 */
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481, 92, 92,

};

#if UCD_BLOCK_SIZE != 128
#error Please correct UCD_BLOCK_SIZE in pcre_internal.h
#endif
#endif  /* SUPPORT_UCP */
/*autoconv-0001 C:\projects\pcre-8.31\pcre_ucd.c converted to PCREUCD8*/
/*autoconv-0010 PCREUCD8 line: 2 added HAVE_CONFIG_H*/
/*autoconv-0011 PCREUCD8 line: 5 config.h replaced by CONFIG.h*/
/*autoconv-0011 PCREUCD8 line: 8 pcre_internal.h replaced by INTERNA8.h*/
./ ADD NAME=DFTABLES 
/*************************************************
*      Perl-Compatible Regular Expressions       *
*************************************************/

/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.

                       Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge

-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/


/* This is a freestanding support program to generate a file containing
character tables for PCRE. The tables are built according to the current
locale. Now that MAKETAB8 is a function visible to the outside world, we
make use of its code from here in order to be consistent. */

#ifndef HAVE_CONFIG_H
#   define HAVE_CONFIG_H 1
#endif
#ifdef HAVE_CONFIG_H
#include "CONFIG.h"
#endif

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>

#include "INTERNA8.h"

#define DFTABLES          /* MAKETAB8.c notices this */
#include "MAKETAB8.c"


int main(int argc, char **argv)
{
FILE *f;
int i = 1;
const unsigned char *tables;
const unsigned char *base_of_tables;

/* By default, the default C locale is used rather than what the building user
happens to have set. However, if the -L option is given, set the locale from
the LC_xxx environment variables. */

if (argc > 1 && strcmp(argv[1], "-L") == 0)
  {
  setlocale(LC_ALL, "");        /* Set from environment variables */
  i++;
  }

if (argc < i + 1)
  {
  fprintf(stderr, "DFTABLES: one filename argument is required\n");
  return 1;
  }

tables = MAKETAB8();
base_of_tables = tables;

f = fopen(argv[i], "w");
if (f == NULL)
  {
  fprintf(stderr, "DFTABLES: failed to open %s for writing\n", argv[1]);
  return 1;
  }

/* There are several fprintf() calls here, because gcc in pedantic mode
complains about the very long string otherwise. */

fprintf(f,
  "/*************************************************\n"
  "*      Perl-Compatible Regular Expressions       *\n"
  "*************************************************/\n\n"
  "/* This file was automatically written by the DFTABLES auxiliary\n"
  "program. It contains character tables that are used when no external\n"
  "tables are passed to PCRE by the application that calls it. The tables\n"
  "are used only for characters whose code values are less than 256.\n\n");
fprintf(f,
  "The following #includes are present because without them gcc 4.x may remove\n"
  "the array definition from the final binary if PCRE is built into a static\n"
  "library and dead code stripping is activated. This leads to link errors.\n"
  "Pulling in the header ensures that the array gets flagged as \"someone\n"
  "outside this compilation unit might reference this\" and so it will always\n"
  "be supplied to the linker. */\n\n"
 /* ZA - force config.h in z/OS */
 #if defined NATIVE_ZOS
  "#ifndef HAVE_CONFIG_H\n"
  "#define HAVE_CONFIG_H 1\n"
  "#endif\n"
 #endif
  "#ifdef HAVE_CONFIG_H\n"
  "#include \"CONFIG.h\"\n"
  "#endif\n\n"
  "#include \"INTERNA8.h\"\n\n");
fprintf(f,
  "const pcre_uint8 PRIV(default_tables)[] = {\n\n"
  "/* This table is a lower casing table. */\n\n");

fprintf(f, "  ");
for (i = 0; i < 256; i++)
  {
  if ((i & 7) == 0 && i != 0) fprintf(f, "\n  ");
  fprintf(f, "%3d", *tables++);
  if (i != 255) fprintf(f, ",");
  }
fprintf(f, ",\n\n");

fprintf(f, "/* This table is a case flipping table. */\n\n");

fprintf(f, "  ");
for (i = 0; i < 256; i++)
  {
  if ((i & 7) == 0 && i != 0) fprintf(f, "\n  ");
  fprintf(f, "%3d", *tables++);
  if (i != 255) fprintf(f, ",");
  }
fprintf(f, ",\n\n");

fprintf(f,
  "/* This table contains bit maps for various character classes.\n"
  "Each map is 32 bytes long and the bits run from the least\n"
  "significant end of each byte. The classes that have their own\n"
  "maps are: space, xdigit, digit, upper, lower, word, graph\n"
  "print, punct, and cntrl. Other classes are built from combinations. */\n\n");

fprintf(f, "  ");
for (i = 0; i < cbit_length; i++)
  {
  if ((i & 7) == 0 && i != 0)
    {
    if ((i & 31) == 0) fprintf(f, "\n");
    fprintf(f, "\n  ");
    }
  fprintf(f, "0x%02x", *tables++);
  if (i != cbit_length - 1) fprintf(f, ",");
  }
fprintf(f, ",\n\n");

fprintf(f,
  "/* This table identifies various classes of character by individual bits:\n"
  "  0x%02x   white space character\n"
  "  0x%02x   letter\n"
  "  0x%02x   decimal digit\n"
  "  0x%02x   hexadecimal digit\n"
  "  0x%02x   alphanumeric or '_'\n"
  "  0x%02x   regular expression metacharacter or binary zero\n*/\n\n",
  ctype_space, ctype_letter, ctype_digit, ctype_xdigit, ctype_word,
  ctype_meta);

fprintf(f, "  ");
for (i = 0; i < 256; i++)
  {
  if ((i & 7) == 0 && i != 0)
    {
    fprintf(f, " /* ");
    if (isprint(i-8)) fprintf(f, " %c -", i-8);
      else fprintf(f, "%3d-", i-8);
    if (isprint(i-1)) fprintf(f, " %c ", i-1);
      else fprintf(f, "%3d", i-1);
    fprintf(f, " */\n  ");
    }
  fprintf(f, "0x%02x", *tables++);
  if (i != 255) fprintf(f, ",");
  }

fprintf(f, "};/* ");
if (isprint(i-8)) fprintf(f, " %c -", i-8);
  else fprintf(f, "%3d-", i-8);
if (isprint(i-1)) fprintf(f, " %c ", i-1);
  else fprintf(f, "%3d", i-1);
fprintf(f, " */\n\n/* End of CHARTAB8.c */\n");

fclose(f);
free((void *)base_of_tables);
return 0;
}

/* End of DFTABLES.c */
/*autoconv-0001 C:\projects\pcre-8.31\dftables.c converted to DFTABLES*/
/*autoconv-0013 DFTABLES line: 43 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0010 DFTABLES line: 47 added HAVE_CONFIG_H*/
/*autoconv-0011 DFTABLES line: 50 config.h replaced by CONFIG.h*/
/*autoconv-0011 DFTABLES line: 58 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 DFTABLES line: 60 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0011 DFTABLES line: 61 pcre_maketables.c replaced by MAKETAB8.c*/
/*autoconv-0013 DFTABLES line: 83 dftables replaced by DFTABLES*/
/*autoconv-0013 DFTABLES line: 87 pcre_maketables replaced by MAKETAB8*/
/*autoconv-0015 DFTABLES line: 90 fopen "wb" replaced by "w"*/
/*autoconv-0013 DFTABLES line: 93 dftables replaced by DFTABLES*/
/*autoconv-0013 DFTABLES line: 104 dftables replaced by DFTABLES*/
/*autoconv-0011 DFTABLES line: 122 config.h replaced by CONFIG.h*/
/*autoconv-0011 DFTABLES line: 124 pcre_internal.h replaced by INTERNA8.h*/
/*autoconv-0013 DFTABLES line: 201 pcre_chartables replaced by CHARTAB8*/
/*autoconv-0013 DFTABLES line: 208 dftables replaced by DFTABLES*/
