Diff for /embedaddon/pcre/pcre_exec.c between versions 1.1.1.3 and 1.1.1.5

version 1.1.1.3, 2012/10/09 09:19:17 version 1.1.1.5, 2014/06/15 19:46:04
Line 6 Line 6
 and semantics are as close as possible to those of the Perl 5 language.  and semantics are as close as possible to those of the Perl 5 language.
   
                        Written by Philip Hazel                         Written by Philip Hazel
           Copyright (c) 1997-2012 University of Cambridge           Copyright (c) 1997-2013 University of Cambridge
   
 -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 56  possible. There are also some static supporting functi Line 56  possible. There are also some static supporting functi
 #undef min  #undef min
 #undef max  #undef max
   
   /* The md->capture_last field uses the lower 16 bits for the last captured
   substring (which can never be greater than 65535) and a bit in the top half
   to mean "capture vector overflowed". This odd way of doing things was
   implemented when it was realized that preserving and restoring the overflow bit
   whenever the last capture number was saved/restored made for a neater
   interface, and doing it this way saved on (a) another variable, which would
   have increased the stack frame size (a big NO-NO in PCRE) and (b) another
   separate set of save/restore instructions. The following defines are used in
   implementing this. */
   
   #define CAPLMASK    0x0000ffff    /* The bits used for last_capture */
   #define OVFLMASK    0xffff0000    /* The bits used for the overflow flag */
   #define OVFLBIT     0x00010000    /* The bit that is set for overflow */
   
 /* Values for setting in md->match_function_type to indicate two special types  /* 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,  of call to match(). We do it this way to save on using another stack variable,
 as stack usage is to be discouraged. */  as stack usage is to be discouraged. */
Line 73  defined PCRE_ERROR_xxx codes, which are all negative.  Line 87  defined PCRE_ERROR_xxx codes, which are all negative. 
 negative to avoid the external error codes. */  negative to avoid the external error codes. */
   
 #define MATCH_ACCEPT       (-999)  #define MATCH_ACCEPT       (-999)
#define MATCH_COMMIT       (-998)#define MATCH_KETRPOS      (-998)
#define MATCH_KETRPOS      (-997)#define MATCH_ONCE         (-997)
#define MATCH_ONCE         (-996)/* The next 5 must be kept together and in sequence so that a test that checks
 for any one of them can use a range. */
 #define MATCH_COMMIT       (-996)
 #define MATCH_PRUNE        (-995)  #define MATCH_PRUNE        (-995)
 #define MATCH_SKIP         (-994)  #define MATCH_SKIP         (-994)
 #define MATCH_SKIP_ARG     (-993)  #define MATCH_SKIP_ARG     (-993)
 #define MATCH_THEN         (-992)  #define MATCH_THEN         (-992)
   #define MATCH_BACKTRACK_MAX MATCH_THEN
   #define MATCH_BACKTRACK_MIN MATCH_COMMIT
   
 /* Maximum number of ints of offset to save on the stack for recursive calls.  /* 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,  If the offset vector is bigger, malloc is used. This should be a multiple of 3,
Line 89  because the offset vector is always a multiple of 3 lo Line 107  because the offset vector is always a multiple of 3 lo
   
 /* Min and max values for the common repeats; for the maxima, 0 => infinity */  /* 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_min[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, };
static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };static const char rep_max[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, };
   
   
   
 #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
 /*************************************************  /*************************************************
 *        Debugging function to print chars       *  *        Debugging function to print chars       *
Line 114  Returns:     nothing Line 130  Returns:     nothing
 static void  static void
 pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)  pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)
 {  {
unsigned int c;pcre_uint32 c;
 BOOL utf = md->utf;
 if (is_subject && length > md->end_subject - p) length = md->end_subject - p;  if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
 while (length-- > 0)  while (length-- > 0)
  if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);  if (isprint(c = RAWUCHARINCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
 }  }
 #endif  #endif
   
Line 150  match_ref(int offset, register PCRE_PUCHAR eptr, int l Line 167  match_ref(int offset, register PCRE_PUCHAR eptr, int l
 {  {
 PCRE_PUCHAR eptr_start = eptr;  PCRE_PUCHAR eptr_start = eptr;
 register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset];  register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset];
   #if defined SUPPORT_UTF && defined SUPPORT_UCP
   BOOL utf = md->utf;
   #endif
   
 #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
 if (eptr >= md->end_subject)  if (eptr >= md->end_subject)
Line 175  ASCII characters. */ Line 195  ASCII characters. */
   
 if (caseless)  if (caseless)
   {    {
#ifdef SUPPORT_UTF#if defined SUPPORT_UTF && defined SUPPORT_UCP
#ifdef SUPPORT_UCP  if (utf)
  if (md->utf) 
     {      {
     /* Match characters up to the end of the reference. NOTE: the number of      /* 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    data units matched may differ, because in UTF-8 there are some characters
    lower case versions code as different numbers of bytes. For example, U+023A    whose upper and lower case versions code have different numbers of bytes.
    (2 bytes in UTF-8) is the upper case version of U+2C65 (3 bytes in UTF-8);    For example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65
    a sequence of 3 of the former uses 6 bytes, as does a sequence of two of    (3 bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a
    the latter. It is important, therefore, to check the length along the    sequence of two of the latter. It is important, therefore, to check the
    reference, not along the subject (earlier code did this wrong). */    length along the reference, not along the subject (earlier code did this
     wrong). */
   
     PCRE_PUCHAR endptr = p + length;      PCRE_PUCHAR endptr = p + length;
     while (p < endptr)      while (p < endptr)
       {        {
      int c, d;      pcre_uint32 c, d;
       const ucd_record *ur;
       if (eptr >= md->end_subject) return -2;   /* Partial match */        if (eptr >= md->end_subject) return -2;   /* Partial match */
       GETCHARINC(c, eptr);        GETCHARINC(c, eptr);
       GETCHARINC(d, p);        GETCHARINC(d, p);
      if (c != d && c != UCD_OTHERCASE(d)) return -1;      ur = GET_UCD(d);
       if (c != d && c != d + ur->other_case)
         {
         const pcre_uint32 *pp = PRIV(ucd_caseless_sets) + ur->caseset;
         for (;;)
           {
           if (c < *pp) return -1;
           if (c == *pp++) break;
           }
         }
       }        }
     }      }
   else    else
 #endif  #endif
 #endif  
   
   /* The same code works when not in UTF-8 mode and in UTF-8 mode when there    /* The same code works when not in UTF-8 mode and in UTF-8 mode when there
   is no UCP support. */    is no UCP support. */
     {      {
     while (length-- > 0)      while (length-- > 0)
       {        {
         pcre_uint32 cc, cp;
       if (eptr >= md->end_subject) return -2;   /* Partial match */        if (eptr >= md->end_subject) return -2;   /* Partial match */
      if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1;      cc = RAWUCHARTEST(eptr);
       cp = RAWUCHARTEST(p);
       if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1;
       p++;        p++;
       eptr++;        eptr++;
       }        }
Line 222  else Line 254  else
   while (length-- > 0)    while (length-- > 0)
     {      {
     if (eptr >= md->end_subject) return -2;   /* Partial match */      if (eptr >= md->end_subject) return -2;   /* Partial match */
    if (*p++ != *eptr++) return -1;    if (RAWUCHARINCTEST(p) != RAWUCHARINCTEST(eptr)) return -1;
     }      }
   }    }
   
Line 278  enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM6,  RM7,  RM8, Line 310  enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM6,  RM7,  RM8,
        RM31,  RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,         RM31,  RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,
        RM41,  RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,         RM41,  RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,
        RM51,  RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,         RM51,  RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,
       RM61,  RM62, RM63, RM64, RM65, RM66 };       RM61,  RM62, RM63, RM64, RM65, RM66, RM67 };
   
 /* These versions of the macros use the stack, as normal. There are debugging  /* 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  versions and production versions. Note that the "rw" argument of RMATCH isn't
Line 296  actually used in this definition. */ Line 328  actually used in this definition. */
   }    }
 #define RRETURN(ra) \  #define RRETURN(ra) \
   { \    { \
  printf("match() returned %d from line %d ", ra, __LINE__); \  printf("match() returned %d from line %d\n", ra, __LINE__); \
   return ra; \    return ra; \
   }    }
 #else  #else
Line 387  typedef struct heapframe { Line 419  typedef struct heapframe {
   
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
   int Xprop_type;    int Xprop_type;
  int Xprop_value;  unsigned int Xprop_value;
   int Xprop_fail_result;    int Xprop_fail_result;
   int Xoclength;    int Xoclength;
   pcre_uchar Xocchars[6];    pcre_uchar Xocchars[6];
Line 400  typedef struct heapframe { Line 432  typedef struct heapframe {
   int Xlength;    int Xlength;
   int Xmax;    int Xmax;
   int Xmin;    int Xmin;
  int Xnumber;  unsigned int Xnumber;
   int Xoffset;    int Xoffset;
  int Xop;  unsigned int Xop;
  int Xsave_capture_last;  pcre_int32 Xsave_capture_last;
   int Xsave_offset1, Xsave_offset2, Xsave_offset3;    int Xsave_offset1, Xsave_offset2, Xsave_offset3;
   int Xstacksave[REC_STACK_SAVE_MAX];    int Xstacksave[REC_STACK_SAVE_MAX];
   
Line 488  so they can be ordinary variables in all cases. Mark s Line 520  so they can be ordinary variables in all cases. Mark s
   
 register int  rrc;         /* Returns from recursive calls */  register int  rrc;         /* Returns from recursive calls */
 register int  i;           /* Used for loops not involving calls to RMATCH() */  register int  i;           /* Used for loops not involving calls to RMATCH() */
register unsigned int c;   /* Character values not kept over RMATCH() calls */register pcre_uint32 c;    /* Character values not kept over RMATCH() calls */
 register BOOL utf;         /* Local copy of UTF flag for speed */  register BOOL utf;         /* Local copy of UTF flag for speed */
   
 BOOL minimize, possessive; /* Quantifier options */  BOOL minimize, possessive; /* Quantifier options */
Line 605  BOOL prev_is_word; Line 637  BOOL prev_is_word;
   
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
 int prop_type;  int prop_type;
int prop_value;unsigned int prop_value;
 int prop_fail_result;  int prop_fail_result;
 int oclength;  int oclength;
 pcre_uchar occhars[6];  pcre_uchar occhars[6];
Line 616  int ctype; Line 648  int ctype;
 int length;  int length;
 int max;  int max;
 int min;  int min;
int number;unsigned int number;
 int offset;  int offset;
int op;unsigned int op;
int save_capture_last;pcre_int32 save_capture_last;
 int save_offset1, save_offset2, save_offset3;  int save_offset1, save_offset2, save_offset3;
 int stacksave[REC_STACK_SAVE_MAX];  int stacksave[REC_STACK_SAVE_MAX];
   
Line 737  for (;;) Line 769  for (;;)
     unaltered. */      unaltered. */
   
     else if (rrc == MATCH_SKIP_ARG &&      else if (rrc == MATCH_SKIP_ARG &&
        STRCMP_UC_UC(ecode + 2, md->start_match_ptr) == 0)        STRCMP_UC_UC_TEST(ecode + 2, md->start_match_ptr) == 0)
       {        {
       md->start_match_ptr = eptr;        md->start_match_ptr = eptr;
       RRETURN(MATCH_SKIP);        RRETURN(MATCH_SKIP);
Line 747  for (;;) Line 779  for (;;)
     case OP_FAIL:      case OP_FAIL:
     RRETURN(MATCH_NOMATCH);      RRETURN(MATCH_NOMATCH);
   
     /* COMMIT overrides PRUNE, SKIP, and THEN */  
   
     case OP_COMMIT:      case OP_COMMIT:
     RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,      RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
       eptrb, RM52);        eptrb, RM52);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
        rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG && 
        rrc != MATCH_THEN) 
      RRETURN(rrc); 
     RRETURN(MATCH_COMMIT);      RRETURN(MATCH_COMMIT);
   
     /* PRUNE overrides THEN */  
   
     case OP_PRUNE:      case OP_PRUNE:
     RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,      RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
       eptrb, RM51);        eptrb, RM51);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
     RRETURN(MATCH_PRUNE);      RRETURN(MATCH_PRUNE);
   
     case OP_PRUNE_ARG:      case OP_PRUNE_ARG:
Line 773  for (;;) Line 798  for (;;)
       eptrb, RM56);        eptrb, RM56);
     if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&      if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
          md->mark == NULL) md->mark = ecode + 2;           md->mark == NULL) md->mark = ecode + 2;
    if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
     RRETURN(MATCH_PRUNE);      RRETURN(MATCH_PRUNE);
   
     /* SKIP overrides PRUNE and THEN */  
   
     case OP_SKIP:      case OP_SKIP:
     RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,      RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
       eptrb, RM53);        eptrb, RM53);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      RRETURN(rrc); 
     md->start_match_ptr = eptr;   /* Pass back current position */      md->start_match_ptr = eptr;   /* Pass back current position */
     RRETURN(MATCH_SKIP);      RRETURN(MATCH_SKIP);
   
     /* Note that, for Perl compatibility, SKIP with an argument does NOT set      /* 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    nomatch_mark. When a pattern match ends with a SKIP_ARG for which there was
    pattern that ended with a SKIP for which there was not a matching MARK. */    not a matching mark, we have to re-run the match, ignoring the SKIP_ARG
     that failed and any that precede it (either they also failed, or were not
     triggered). To do this, we maintain a count of executed SKIP_ARGs. If a
     SKIP_ARG gets to top level, the match is re-run with md->ignore_skip_arg
     set to the count of the one that failed. */
   
     case OP_SKIP_ARG:      case OP_SKIP_ARG:
    if (md->ignore_skip_arg)    md->skip_arg_count++;
     if (md->skip_arg_count <= md->ignore_skip_arg)
       {        {
       ecode += PRIV(OP_lengths)[*ecode] + ecode[1];        ecode += PRIV(OP_lengths)[*ecode] + ecode[1];
       break;        break;
       }        }
     RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,      RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
       eptrb, RM57);        eptrb, RM57);
    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
      RRETURN(rrc); 
   
     /* Pass back the current skip name by overloading md->start_match_ptr and      /* 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      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      caught by a matching MARK, or get to the top, where it causes a rematch
    with the md->ignore_skip_arg flag set. */    with md->ignore_skip_arg set to the value of md->skip_arg_count. */
   
     md->start_match_ptr = ecode + 2;      md->start_match_ptr = ecode + 2;
     RRETURN(MATCH_SKIP_ARG);      RRETURN(MATCH_SKIP_ARG);
Line 1050  for (;;) Line 1076  for (;;)
       /* In all other cases, we have to make another call to match(). */        /* In all other cases, we have to make another call to match(). */
   
       save_mark = md->mark;        save_mark = md->mark;
         save_capture_last = md->capture_last;
       RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb,        RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb,
         RM2);          RM2);
   
Line 1081  for (;;) Line 1108  for (;;)
       ecode += GET(ecode, 1);        ecode += GET(ecode, 1);
       md->mark = save_mark;        md->mark = save_mark;
       if (*ecode != OP_ALT) break;        if (*ecode != OP_ALT) break;
         md->capture_last = save_capture_last;
       }        }
   
     RRETURN(MATCH_NOMATCH);      RRETURN(MATCH_NOMATCH);
Line 1143  for (;;) Line 1171  for (;;)
           ecode = md->start_code + code_offset;            ecode = md->start_code + code_offset;
           save_capture_last = md->capture_last;            save_capture_last = md->capture_last;
           matched_once = TRUE;            matched_once = TRUE;
             mstart = md->start_match_ptr;    /* In case \K changed it */
           continue;            continue;
           }            }
   
Line 1202  for (;;) Line 1231  for (;;)
     POSSESSIVE_NON_CAPTURE:      POSSESSIVE_NON_CAPTURE:
     matched_once = FALSE;      matched_once = FALSE;
     code_offset = (int)(ecode - md->start_code);      code_offset = (int)(ecode - md->start_code);
       save_capture_last = md->capture_last;
   
     for (;;)      for (;;)
       {        {
Line 1214  for (;;) Line 1244  for (;;)
         eptr = md->end_match_ptr;          eptr = md->end_match_ptr;
         ecode = md->start_code + code_offset;          ecode = md->start_code + code_offset;
         matched_once = TRUE;          matched_once = TRUE;
           mstart = md->start_match_ptr;   /* In case \K reset it */
         continue;          continue;
         }          }
   
Line 1231  for (;;) Line 1262  for (;;)
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       ecode += GET(ecode, 1);        ecode += GET(ecode, 1);
       if (*ecode != OP_ALT) break;        if (*ecode != OP_ALT) break;
         md->capture_last = save_capture_last;
       }        }
   
     if (matched_once || allow_zero)      if (matched_once || allow_zero)
Line 1242  for (;;) Line 1274  for (;;)
   
     /* Control never reaches here. */      /* Control never reaches here. */
   
    /* Conditional group: compilation checked that there are no more than    /* Conditional group: compilation checked that there are no more than two
    two branches. If the condition is false, skipping the first branch takes us    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    past the end of the item if there is only one branch, but that's exactly
    exactly what going to the ket would do. */    what we want. */
   
     case OP_COND:      case OP_COND:
     case OP_SCOND:      case OP_SCOND:
     codelink = GET(ecode, 1);  
   
       /* The variable codelink will be added to ecode when the condition is
       false, to get to the second branch. Setting it to the offset to the ALT
       or KET, then incrementing ecode achieves this effect. We now have ecode
       pointing to the condition or callout. */
   
       codelink = GET(ecode, 1);   /* Offset to the second branch */
       ecode += 1 + LINK_SIZE;     /* From this opcode */
   
     /* Because of the way auto-callout works during compile, a callout item is      /* Because of the way auto-callout works during compile, a callout item is
     inserted between OP_COND and an assertion condition. */      inserted between OP_COND and an assertion condition. */
   
    if (ecode[LINK_SIZE+1] == OP_CALLOUT)    if (*ecode == OP_CALLOUT)
       {        {
       if (PUBL(callout) != NULL)        if (PUBL(callout) != NULL)
         {          {
         PUBL(callout_block) cb;          PUBL(callout_block) cb;
         cb.version          = 2;   /* Version 1 of the callout block */          cb.version          = 2;   /* Version 1 of the callout block */
        cb.callout_number   = ecode[LINK_SIZE+2];        cb.callout_number   = ecode[1];
         cb.offset_vector    = md->offset_vector;          cb.offset_vector    = md->offset_vector;
#ifdef COMPILE_PCRE8#if defined COMPILE_PCRE8
         cb.subject          = (PCRE_SPTR)md->start_subject;          cb.subject          = (PCRE_SPTR)md->start_subject;
#else#elif defined COMPILE_PCRE16
         cb.subject          = (PCRE_SPTR16)md->start_subject;          cb.subject          = (PCRE_SPTR16)md->start_subject;
   #elif defined COMPILE_PCRE32
           cb.subject          = (PCRE_SPTR32)md->start_subject;
 #endif  #endif
         cb.subject_length   = (int)(md->end_subject - md->start_subject);          cb.subject_length   = (int)(md->end_subject - md->start_subject);
         cb.start_match      = (int)(mstart - md->start_subject);          cb.start_match      = (int)(mstart - md->start_subject);
         cb.current_position = (int)(eptr - md->start_subject);          cb.current_position = (int)(eptr - md->start_subject);
        cb.pattern_position = GET(ecode, LINK_SIZE + 3);        cb.pattern_position = GET(ecode, 2);
        cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE);        cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
         cb.capture_top      = offset_top/2;          cb.capture_top      = offset_top/2;
        cb.capture_last     = md->capture_last;        cb.capture_last     = md->capture_last & CAPLMASK;
         /* Internal change requires this for API compatibility. */
         if (cb.capture_last == 0) cb.capture_last = -1;
         cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
         cb.mark             = md->nomatch_mark;          cb.mark             = md->nomatch_mark;
         if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);          if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
         if (rrc < 0) RRETURN(rrc);          if (rrc < 0) RRETURN(rrc);
         }          }
   
         /* Advance ecode past the callout, so it now points to the condition. We
         must adjust codelink so that the value of ecode+codelink is unchanged. */
   
       ecode += PRIV(OP_lengths)[OP_CALLOUT];        ecode += PRIV(OP_lengths)[OP_CALLOUT];
         codelink -= PRIV(OP_lengths)[OP_CALLOUT];
       }        }
   
    condcode = ecode[LINK_SIZE+1];    /* Test the various possible conditions */
   
    /* Now see what the actual condition is */    condition = FALSE;
    switch(condcode = *ecode)
    if (condcode == OP_RREF || condcode == OP_NRREF)    /* Recursion test */ 
       {        {
      if (md->recursive == NULL)                /* Not recursing => FALSE */      case OP_RREF:         /* Numbered group recursion test */
       if (md->recursive != NULL)     /* Not recursing => FALSE */
         {          {
        condition = FALSE;        unsigned int recno = GET2(ecode, 1);   /* Recursion group number*/
        ecode += GET(ecode, 1); 
        } 
      else 
        { 
        int recno = GET2(ecode, LINK_SIZE + 2);   /* Recursion group number*/ 
         condition = (recno == RREF_ANY || recno == md->recursive->group_num);          condition = (recno == RREF_ANY || recno == md->recursive->group_num);
           }
         break;
   
        /* If the test is for recursion into a specific subpattern, and it is      case OP_DNRREF:       /* Duplicate named group recursion test */
        false, but the test was set up by name, scan the table to see if the      if (md->recursive != NULL)
        name refers to any other numbers, and test them. The condition is true        {
        if any one is set. */        int count = GET2(ecode, 1 + IMM2_SIZE);
        pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
        if (!condition && condcode == OP_NRREF)        while (count-- > 0)
           {            {
          pcre_uchar *slotA = md->name_table;          unsigned int recno = GET2(slot, 0);
          for (i = 0; i < md->name_count; i++)          condition = recno == md->recursive->group_num;
            {          if (condition) break;
            if (GET2(slotA, 0) == recno) break;          slot += md->name_entry_size;
            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);  
         }          }
      }      break;
   
    else if (condcode == OP_CREF || condcode == OP_NCREF)  /* Group used test */      case OP_CREF:         /* Numbered group used test */
      {      offset = GET2(ecode, 1) << 1;  /* Doubled ref number */
      offset = GET2(ecode, LINK_SIZE+2) << 1;  /* Doubled ref number */ 
       condition = offset < offset_top && md->offset_vector[offset] >= 0;        condition = offset < offset_top && md->offset_vector[offset] >= 0;
         break;
   
      /* If the numbered capture is unset, but the reference was by name,      case OP_DNCREF:      /* Duplicate named group used test */
      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;        int count = GET2(ecode, 1 + IMM2_SIZE);
        pcre_uchar *slotA = md->name_table;        pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
        while (count-- > 0)
        for (i = 0; i < md->name_count; i++) 
           {            {
          if (GET2(slotA, 0) == refno) break;          offset = GET2(slot, 0) << 1;
          slotA += md->name_entry_size;          condition = offset < offset_top && md->offset_vector[offset] >= 0;
           if (condition) break;
           slot += 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;  
               }  
             }  
           }  
         }          }
         break;
   
      /* Chose branch according to the condition */      case OP_DEF:     /* DEFINE - always false */
       break;
   
      ecode += condition? 1 + IMM2_SIZE : 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 if (condcode == OP_DEF)     /* DEFINE - always false */      default:
      { 
      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;        md->match_function_type = MATCH_CONDASSERT;
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM3);      RMATCH(eptr, ecode, offset_top, md, NULL, RM3);
       if (rrc == MATCH_MATCH)        if (rrc == MATCH_MATCH)
         {          {
         if (md->end_offset_top > offset_top)          if (md->end_offset_top > offset_top)
           offset_top = md->end_offset_top;  /* Captures may have happened */            offset_top = md->end_offset_top;  /* Captures may have happened */
         condition = TRUE;          condition = TRUE;
        ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2);
         /* Advance ecode past the assertion to the start of the first branch,
         but adjust it so that the general choosing code below works. */
 
         ecode += GET(ecode, 1);
         while (*ecode == OP_ALT) ecode += GET(ecode, 1);          while (*ecode == OP_ALT) ecode += GET(ecode, 1);
           ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode];
         }          }
   
       /* PCRE doesn't allow the effect of (*THEN) to escape beyond an        /* PCRE doesn't allow the effect of (*THEN) to escape beyond an
      assertion; it is therefore treated as NOMATCH. */      assertion; it is therefore treated as NOMATCH. Any other return is an
       error. */
   
       else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)        else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
         {          {
         RRETURN(rrc);         /* Need braces because of following else */          RRETURN(rrc);         /* Need braces because of following else */
         }          }
      else      break;
        { 
        condition = FALSE; 
        ecode += codelink; 
        } 
       }        }
   
    /* We are now at the branch that is to be obeyed. As there is only one, can    /* Choose branch according to the condition */
    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)    ecode += condition? PRIV(OP_lengths)[condcode] : codelink;
 
     /* We are now at the branch that is to be obeyed. As there is only one, we
     can use tail recursion to avoid using another stack frame, except when
     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[-(1+LINK_SIZE)] == OP_ALT)
       {        {
       if (op != OP_SCOND)        if (op != OP_SCOND)
         {          {
         ecode += 1 + LINK_SIZE;  
         goto TAIL_RECURSE;          goto TAIL_RECURSE;
         }          }
   
       md->match_function_type = MATCH_CBEGROUP;        md->match_function_type = MATCH_CBEGROUP;
      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM49);      RMATCH(eptr, ecode, offset_top, md, eptrb, RM49);
       RRETURN(rrc);        RRETURN(rrc);
       }        }
   
Line 1486  for (;;) Line 1442  for (;;)
   
     else      else
       {        {
       ecode += 1 + LINK_SIZE;  
       }        }
     break;      break;
   
Line 1495  for (;;) Line 1450  for (;;)
     to close any currently open capturing brackets. */      to close any currently open capturing brackets. */
   
     case OP_CLOSE:      case OP_CLOSE:
    number = GET2(ecode, 1);    number = GET2(ecode, 1);   /* Must be less than 65536 */
     offset = number << 1;      offset = number << 1;
   
 #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
Line 1503  for (;;) Line 1458  for (;;)
       printf("\n");        printf("\n");
 #endif  #endif
   
    md->capture_last = number;    md->capture_last = (md->capture_last & OVFLMASK) | number;
    if (offset >= md->offset_max) md->offset_overflow = TRUE; else    if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
       {        {
       md->offset_vector[offset] =        md->offset_vector[offset] =
         md->offset_vector[md->offset_end - number];          md->offset_vector[md->offset_end - number];
Line 1566  for (;;) Line 1521  for (;;)
       }        }
     else condassert = FALSE;      else condassert = FALSE;
   
       /* Loop for each branch */
   
     do      do
       {        {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);
   
         /* A match means that the assertion is true; break out of the loop
         that matches its alternatives. */
   
       if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)        if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
         {          {
         mstart = md->start_match_ptr;   /* In case \K reset it */          mstart = md->start_match_ptr;   /* In case \K reset it */
         break;          break;
         }          }
   
         /* If not matched, restore the previous mark setting. */
   
       md->mark = save_mark;        md->mark = save_mark;
   
      /* A COMMIT failure must fail the entire assertion, without trying any      /* See comment in the code for capturing groups above about handling
      subsequent branches. */      THEN. */
   
      if (rrc == MATCH_COMMIT) RRETURN(MATCH_NOMATCH);      if (rrc == MATCH_THEN)
         {
         next = ecode + GET(ecode,1);
         if (md->start_match_ptr < next &&
             (*ecode == OP_ALT || *next == OP_ALT))
           rrc = MATCH_NOMATCH;
         }
   
      /* PCRE does not allow THEN to escape beyond an assertion; it      /* Anything other than NOMATCH causes the entire assertion to fail,
      is treated as NOMATCH. */      passing back the return code. This includes COMMIT, SKIP, PRUNE and an
       uncaptured THEN, which means they take their normal effect. This
       consistent approach does not always have exactly the same effect as in
       Perl. */
   
      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       ecode += GET(ecode, 1);        ecode += GET(ecode, 1);
       }        }
    while (*ecode == OP_ALT);    while (*ecode == OP_ALT);   /* Continue for next alternative */
   
       /* If we have tried all the alternative branches, the assertion has
       failed. If not, we broke out after a match. */
   
     if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);      if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);
   
     /* If checking an assertion for a condition, return MATCH_MATCH. */      /* If checking an assertion for a condition, return MATCH_MATCH. */
   
     if (condassert) RRETURN(MATCH_MATCH);      if (condassert) RRETURN(MATCH_MATCH);
   
    /* Continue from after the assertion, updating the offsets high water    /* Continue from after a successful assertion, updating the offsets high
    mark, since extracts may have been taken during the assertion. */    water mark, since extracts may have been taken during the assertion. */
   
     do ecode += GET(ecode,1); while (*ecode == OP_ALT);      do ecode += GET(ecode,1); while (*ecode == OP_ALT);
     ecode += 1 + LINK_SIZE;      ecode += 1 + LINK_SIZE;
     offset_top = md->end_offset_top;      offset_top = md->end_offset_top;
     continue;      continue;
   
    /* Negative assertion: all branches must fail to match. Encountering SKIP,    /* Negative assertion: all branches must fail to match for the assertion to
    PRUNE, or COMMIT means we must assume failure without checking subsequent    succeed. */
    branches. */ 
   
     case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
     case OP_ASSERTBACK_NOT:      case OP_ASSERTBACK_NOT:
Line 1617  for (;;) Line 1592  for (;;)
       }        }
     else condassert = FALSE;      else condassert = FALSE;
   
       /* Loop for each alternative branch. */
   
     do      do
       {        {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);
      md->mark = save_mark;      md->mark = save_mark;   /* Always restore the mark setting */
      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) RRETURN(MATCH_NOMATCH);
      if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT)      switch(rrc)
         {          {
        do ecode += GET(ecode,1); while (*ecode == OP_ALT);        case MATCH_MATCH:            /* A successful match means */
         case MATCH_ACCEPT:           /* the assertion has failed. */
         RRETURN(MATCH_NOMATCH);
 
         case MATCH_NOMATCH:          /* Carry on with next branch */
         break;          break;
   
           /* See comment in the code for capturing groups above about handling
           THEN. */
   
           case MATCH_THEN:
           next = ecode + GET(ecode,1);
           if (md->start_match_ptr < next &&
               (*ecode == OP_ALT || *next == OP_ALT))
             {
             rrc = MATCH_NOMATCH;
             break;
             }
           /* Otherwise fall through. */
   
           /* COMMIT, SKIP, PRUNE, and an uncaptured THEN cause the whole
           assertion to fail to match, without considering any more alternatives.
           Failing to match means the assertion is true. This is a consistent
           approach, but does not always have the same effect as in Perl. */
   
           case MATCH_COMMIT:
           case MATCH_SKIP:
           case MATCH_SKIP_ARG:
           case MATCH_PRUNE:
           do ecode += GET(ecode,1); while (*ecode == OP_ALT);
           goto NEG_ASSERT_TRUE;   /* Break out of alternation loop */
   
           /* Anything else is an error */
   
           default:
           RRETURN(rrc);
         }          }
   
      /* PCRE does not allow THEN to escape beyond an assertion; it is treated      /* Continue with next branch */
      as NOMATCH. */ 
   
       if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);  
       ecode += GET(ecode,1);        ecode += GET(ecode,1);
       }        }
     while (*ecode == OP_ALT);      while (*ecode == OP_ALT);
   
    if (condassert) RRETURN(MATCH_MATCH);  /* Condition assertion */    /* All branches in the assertion failed to match. */
   
    ecode += 1 + LINK_SIZE;    NEG_ASSERT_TRUE:
     if (condassert) RRETURN(MATCH_MATCH);  /* Condition assertion */
     ecode += 1 + LINK_SIZE;                /* Continue with current branch */
     continue;      continue;
   
     /* Move the subject pointer back. This occurs only at the start of      /* Move the subject pointer back. This occurs only at the start of
Line 1685  for (;;) Line 1696  for (;;)
       cb.version          = 2;   /* Version 1 of the callout block */        cb.version          = 2;   /* Version 1 of the callout block */
       cb.callout_number   = ecode[1];        cb.callout_number   = ecode[1];
       cb.offset_vector    = md->offset_vector;        cb.offset_vector    = md->offset_vector;
#ifdef COMPILE_PCRE8#if defined COMPILE_PCRE8
       cb.subject          = (PCRE_SPTR)md->start_subject;        cb.subject          = (PCRE_SPTR)md->start_subject;
#else#elif defined COMPILE_PCRE16
       cb.subject          = (PCRE_SPTR16)md->start_subject;        cb.subject          = (PCRE_SPTR16)md->start_subject;
   #elif defined COMPILE_PCRE32
         cb.subject          = (PCRE_SPTR32)md->start_subject;
 #endif  #endif
       cb.subject_length   = (int)(md->end_subject - md->start_subject);        cb.subject_length   = (int)(md->end_subject - md->start_subject);
       cb.start_match      = (int)(mstart - md->start_subject);        cb.start_match      = (int)(mstart - md->start_subject);
Line 1696  for (;;) Line 1709  for (;;)
       cb.pattern_position = GET(ecode, 2);        cb.pattern_position = GET(ecode, 2);
       cb.next_item_length = GET(ecode, 2 + LINK_SIZE);        cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
       cb.capture_top      = offset_top/2;        cb.capture_top      = offset_top/2;
      cb.capture_last     = md->capture_last;      cb.capture_last     = md->capture_last & CAPLMASK;
       /* Internal change requires this for API compatibility. */
       if (cb.capture_last == 0) cb.capture_last = -1;
       cb.callout_data     = md->callout_data;        cb.callout_data     = md->callout_data;
       cb.mark             = md->nomatch_mark;        cb.mark             = md->nomatch_mark;
       if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);        if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
Line 1725  for (;;) Line 1740  for (;;)
     case OP_RECURSE:      case OP_RECURSE:
       {        {
       recursion_info *ri;        recursion_info *ri;
      int recno;      unsigned int recno;
   
       callpat = md->start_code + GET(ecode, 1);        callpat = md->start_code + GET(ecode, 1);
       recno = (callpat == md->start_code)? 0 :        recno = (callpat == md->start_code)? 0 :
Line 1742  for (;;) Line 1757  for (;;)
       /* Add to "recursing stack" */        /* Add to "recursing stack" */
   
       new_recursive.group_num = recno;        new_recursive.group_num = recno;
         new_recursive.saved_capture_last = md->capture_last;
       new_recursive.subject_position = eptr;        new_recursive.subject_position = eptr;
       new_recursive.prevrec = md->recursive;        new_recursive.prevrec = md->recursive;
       md->recursive = &new_recursive;        md->recursive = &new_recursive;
Line 1765  for (;;) Line 1781  for (;;)
             new_recursive.saved_max * sizeof(int));              new_recursive.saved_max * sizeof(int));
   
       /* OK, now we can do the recursion. After processing each alternative,        /* OK, now we can do the recursion. After processing each alternative,
      restore the offset data. If there were nested recursions, md->recursive      restore the offset data and the last captured value. If there were nested
      might be changed, so reset it before looping. */      recursions, md->recursive might be changed, so reset it before looping.
       */
   
       DPRINTF(("Recursing into group %d\n", new_recursive.group_num));        DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
       cbegroup = (*callpat >= OP_SBRA);        cbegroup = (*callpat >= OP_SBRA);
Line 1777  for (;;) Line 1794  for (;;)
           md, eptrb, RM6);            md, eptrb, RM6);
         memcpy(md->offset_vector, new_recursive.offset_save,          memcpy(md->offset_vector, new_recursive.offset_save,
             new_recursive.saved_max * sizeof(int));              new_recursive.saved_max * sizeof(int));
           md->capture_last = new_recursive.saved_capture_last;
         md->recursive = new_recursive.prevrec;          md->recursive = new_recursive.prevrec;
         if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)          if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
           {            {
Line 1793  for (;;) Line 1811  for (;;)
           goto RECURSION_MATCHED;        /* Exit loop; end processing */            goto RECURSION_MATCHED;        /* Exit loop; end processing */
           }            }
   
        /* PCRE does not allow THEN or COMMIT to escape beyond a recursion; it        /* PCRE does not allow THEN, SKIP, PRUNE or COMMIT to escape beyond a
        is treated as NOMATCH. */        recursion; they cause a NOMATCH for the entire recursion. These codes
         are defined in a range that can be tested for. */
   
        else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN &&        if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX)
                 rrc != MATCH_COMMIT)          RRETURN(MATCH_NOMATCH);
 
         /* Any return code other than NOMATCH is an error. */
 
         if (rrc != MATCH_NOMATCH)
           {            {
           DPRINTF(("Recursion gave error %d\n", rrc));            DPRINTF(("Recursion gave error %d\n", rrc));
           if (new_recursive.offset_save != stacksave)            if (new_recursive.offset_save != stacksave)
Line 1927  for (;;) Line 1950  for (;;)
   
       /* Deal with capturing */        /* Deal with capturing */
   
      md->capture_last = number;      md->capture_last = (md->capture_last & OVFLMASK) | number;
      if (offset >= md->offset_max) md->offset_overflow = TRUE; else      if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
         {          {
         /* If offset is greater than offset_top, it means that we are          /* If offset is greater than offset_top, it means that we are
         "skipping" a capturing group, and that group's offsets must be marked          "skipping" a capturing group, and that group's offsets must be marked
Line 1984  for (;;) Line 2007  for (;;)
   
     if (*ecode == OP_KETRPOS)      if (*ecode == OP_KETRPOS)
       {        {
         md->start_match_ptr = mstart;    /* In case \K reset it */
       md->end_match_ptr = eptr;        md->end_match_ptr = eptr;
       md->end_offset_top = offset_top;        md->end_offset_top = offset_top;
       RRETURN(MATCH_KETRPOS);        RRETURN(MATCH_KETRPOS);
Line 2079  for (;;) Line 2103  for (;;)
             eptr + 1 >= md->end_subject &&              eptr + 1 >= md->end_subject &&
             NLBLOCK->nltype == NLTYPE_FIXED &&              NLBLOCK->nltype == NLTYPE_FIXED &&
             NLBLOCK->nllen == 2 &&              NLBLOCK->nllen == 2 &&
            *eptr == NLBLOCK->nl[0])            RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
           {            {
           md->hitend = TRUE;            md->hitend = TRUE;
           if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);            if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
Line 2123  for (;;) Line 2147  for (;;)
           eptr + 1 >= md->end_subject &&            eptr + 1 >= md->end_subject &&
           NLBLOCK->nltype == NLTYPE_FIXED &&            NLBLOCK->nltype == NLTYPE_FIXED &&
           NLBLOCK->nllen == 2 &&            NLBLOCK->nllen == 2 &&
          *eptr == NLBLOCK->nl[0])          RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
         {          {
         md->hitend = TRUE;          md->hitend = TRUE;
         if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);          if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
Line 2266  for (;;) Line 2290  for (;;)
         eptr + 1 >= md->end_subject &&          eptr + 1 >= md->end_subject &&
         NLBLOCK->nltype == NLTYPE_FIXED &&          NLBLOCK->nltype == NLTYPE_FIXED &&
         NLBLOCK->nllen == 2 &&          NLBLOCK->nllen == 2 &&
        *eptr == NLBLOCK->nl[0])        RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
       {        {
       md->hitend = TRUE;        md->hitend = TRUE;
       if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);        if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
Line 2415  for (;;) Line 2439  for (;;)
       {        {
       default: RRETURN(MATCH_NOMATCH);        default: RRETURN(MATCH_NOMATCH);
   
      case 0x000d:      case CHAR_CR:
       if (eptr >= md->end_subject)        if (eptr >= md->end_subject)
         {          {
         SCHECK_PARTIAL();          SCHECK_PARTIAL();
         }          }
      else if (*eptr == 0x0a) eptr++;      else if (RAWUCHARTEST(eptr) == CHAR_LF) eptr++;
       break;        break;
   
      case 0x000a:      case CHAR_LF:
       break;        break;
   
      case 0x000b:      case CHAR_VT:
      case 0x000c:      case CHAR_FF:
      case 0x0085:      case CHAR_NEL:
 #ifndef EBCDIC
       case 0x2028:        case 0x2028:
       case 0x2029:        case 0x2029:
   #endif  /* Not EBCDIC */
       if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);        if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
       break;        break;
       }        }
Line 2446  for (;;) Line 2472  for (;;)
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
         HSPACE_CASES: RRETURN(MATCH_NOMATCH);  /* Byte and multibyte cases */
       default: break;        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++;      ecode++;
     break;      break;
Line 2480  for (;;) Line 2487  for (;;)
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
         HSPACE_CASES: break;  /* Byte and multibyte cases */
       default: RRETURN(MATCH_NOMATCH);        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++;      ecode++;
     break;      break;
Line 2514  for (;;) Line 2502  for (;;)
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
         VSPACE_CASES: RRETURN(MATCH_NOMATCH);
       default: break;        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++;      ecode++;
     break;      break;
Line 2536  for (;;) Line 2517  for (;;)
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
         VSPACE_CASES: break;
       default: RRETURN(MATCH_NOMATCH);        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++;      ecode++;
     break;      break;
Line 2562  for (;;) Line 2536  for (;;)
       }        }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
       {        {
         const pcre_uint32 *cp;
       const ucd_record *prop = GET_UCD(c);        const ucd_record *prop = GET_UCD(c);
   
       switch(ecode[1])        switch(ecode[1])
Line 2600  for (;;) Line 2575  for (;;)
           RRETURN(MATCH_NOMATCH);            RRETURN(MATCH_NOMATCH);
         break;          break;
   
        case PT_SPACE:    /* Perl space */        /* Perl space used to exclude VT, but from Perl 5.18 it is included,
        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||        which means that Perl space and POSIX space are now identical. PCRE
             c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)        was changed at release 8.34. */
               == (op == OP_NOTPROP)) 
          RRETURN(MATCH_NOMATCH); 
        break; 
   
           case PT_SPACE:    /* Perl space */
         case PT_PXSPACE:  /* POSIX space */          case PT_PXSPACE:  /* POSIX space */
        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||        switch(c)
             c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||          {
             c == CHAR_FF || c == CHAR_CR)          HSPACE_CASES:
               == (op == OP_NOTPROP))          VSPACE_CASES:
          RRETURN(MATCH_NOMATCH);          if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
           break;
 
           default:
           if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) ==
             (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH);
           break;
           }
         break;          break;
   
         case PT_WORD:          case PT_WORD:
Line 2622  for (;;) Line 2602  for (;;)
           RRETURN(MATCH_NOMATCH);            RRETURN(MATCH_NOMATCH);
         break;          break;
   
           case PT_CLIST:
           cp = PRIV(ucd_caseless_sets) + ecode[2];
           for (;;)
             {
             if (c < *cp)
               { if (op == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; }
             if (c == *cp++)
               { if (op == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } }
             }
           break;
   
           case PT_UCNC:
           if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
                c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
                c >= 0xe000) == (op == OP_NOTPROP))
             RRETURN(MATCH_NOMATCH);
           break;
   
         /* This should never occur */          /* This should never occur */
   
         default:          default:
Line 2641  for (;;) Line 2639  for (;;)
       SCHECK_PARTIAL();        SCHECK_PARTIAL();
       RRETURN(MATCH_NOMATCH);        RRETURN(MATCH_NOMATCH);
       }        }
    GETCHARINCTEST(c, eptr);    else
    if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); 
    while (eptr < md->end_subject) 
       {        {
      int len = 1;      int lgb, rgb;
      if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }      GETCHARINCTEST(c, eptr);
      if (UCD_CATEGORY(c) != ucp_M) break;      lgb = UCD_GRAPHBREAK(c);
      eptr += len;      while (eptr < md->end_subject)
         {
         int len = 1;
         if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
         rgb = UCD_GRAPHBREAK(c);
         if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
         lgb = rgb;
         eptr += len;
         }
       }        }
     CHECK_PARTIAL();      CHECK_PARTIAL();
     ecode++;      ecode++;
     break;      break;
#endif#endif  /* SUPPORT_UCP */
   
   
     /* Match a back reference, possibly repeatedly. Look past the end of the      /* Match a back reference, possibly repeatedly. Look past the end of the
Line 2662  for (;;) Line 2666  for (;;)
     similar code to character type repeats - written out again for speed.      similar code to character type repeats - written out again for speed.
     However, if the referenced string is the empty string, always treat      However, if the referenced string is the empty string, always treat
     it as matched, any number of times (otherwise there could be infinite      it as matched, any number of times (otherwise there could be infinite
    loops). */    loops). If the reference is unset, there are two possibilities:
   
     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;      (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      this ensures that every attempt at a match fails. We can't just fail
     here, because of the possibility of quantifiers with zero minima.      here, because of the possibility of quantifiers with zero minima.
Line 2680  for (;;) Line 2676  for (;;)
     so that the back reference matches an empty string.      so that the back reference matches an empty string.
   
     Otherwise, set the length to the length of what was matched by the      Otherwise, set the length to the length of what was matched by the
    referenced subpattern. */    referenced subpattern.
   
       The OP_REF and OP_REFI opcodes are used for a reference to a numbered group
       or to a non-duplicated named group. For a duplicated named group, OP_DNREF
       and OP_DNREFI are used. In this case we must scan the list of groups to
       which the name refers, and use the first one that is set. */
   
       case OP_DNREF:
       case OP_DNREFI:
       caseless = op == OP_DNREFI;
         {
         int count = GET2(ecode, 1+IMM2_SIZE);
         pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
         ecode += 1 + 2*IMM2_SIZE;
   
         while (count-- > 0)
           {
           offset = GET2(slot, 0) << 1;
           if (offset < offset_top && md->offset_vector[offset] >= 0) break;
           slot += md->name_entry_size;
           }
         if (count < 0)
           length = (md->jscript_compat)? 0 : -1;
         else
           length = md->offset_vector[offset+1] - md->offset_vector[offset];
         }
       goto REF_REPEAT;
   
       case OP_REF:
       case OP_REFI:
       caseless = op == OP_REFI;
       offset = GET2(ecode, 1) << 1;               /* Doubled ref number */
       ecode += 1 + IMM2_SIZE;
     if (offset >= offset_top || md->offset_vector[offset] < 0)      if (offset >= offset_top || md->offset_vector[offset] < 0)
       length = (md->jscript_compat)? 0 : -1;        length = (md->jscript_compat)? 0 : -1;
     else      else
Line 2689  for (;;) Line 2716  for (;;)
   
     /* Set up for repetition, or handle the non-repeated case */      /* Set up for repetition, or handle the non-repeated case */
   
       REF_REPEAT:
     switch (*ecode)      switch (*ecode)
       {        {
       case OP_CRSTAR:        case OP_CRSTAR:
Line 2837  for (;;) Line 2865  for (;;)
         case OP_CRMINPLUS:          case OP_CRMINPLUS:
         case OP_CRQUERY:          case OP_CRQUERY:
         case OP_CRMINQUERY:          case OP_CRMINQUERY:
           case OP_CRPOSSTAR:
           case OP_CRPOSPLUS:
           case OP_CRPOSQUERY:
         c = *ecode++ - OP_CRSTAR;          c = *ecode++ - OP_CRSTAR;
        minimize = (c & 1) != 0;        if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0;
         else possessive = TRUE;
         min = rep_min[c];                 /* Pick up values from tables; */          min = rep_min[c];                 /* Pick up values from tables; */
         max = rep_max[c];                 /* zero for max => infinity */          max = rep_max[c];                 /* zero for max => infinity */
         if (max == 0) max = INT_MAX;          if (max == 0) max = INT_MAX;
Line 2846  for (;;) Line 2878  for (;;)
   
         case OP_CRRANGE:          case OP_CRRANGE:
         case OP_CRMINRANGE:          case OP_CRMINRANGE:
           case OP_CRPOSRANGE:
         minimize = (*ecode == OP_CRMINRANGE);          minimize = (*ecode == OP_CRMINRANGE);
           possessive = (*ecode == OP_CRPOSRANGE);
         min = GET2(ecode, 1);          min = GET2(ecode, 1);
         max = GET2(ecode, 1 + IMM2_SIZE);          max = GET2(ecode, 1 + IMM2_SIZE);
         if (max == 0) max = INT_MAX;          if (max == 0) max = INT_MAX;
Line 2988  for (;;) Line 3022  for (;;)
               if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;                if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
             eptr += len;              eptr += len;
             }              }
   
             if (possessive) continue;    /* No backtracking */
   
           for (;;)            for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);
Line 3018  for (;;) Line 3055  for (;;)
               if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;                if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
             eptr++;              eptr++;
             }              }
   
             if (possessive) continue;    /* No backtracking */
   
           while (eptr >= pp)            while (eptr >= pp)
             {              {
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM19);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM19);
Line 3033  for (;;) Line 3073  for (;;)
     /* Control never gets here */      /* Control never gets here */
   
   
    /* Match an extended character class. This opcode is encountered only    /* Match an extended character class. In the 8-bit library, this opcode is
    when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8    encountered only when UTF-8 mode mode is supported. In the 16-bit and
    mode, because Unicode properties are supported in non-UTF-8 mode. */    32-bit libraries, codepoints greater than 255 may be encountered even when
     UTF is not supported. */
   
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
     case OP_XCLASS:      case OP_XCLASS:
Line 3051  for (;;) Line 3092  for (;;)
         case OP_CRMINPLUS:          case OP_CRMINPLUS:
         case OP_CRQUERY:          case OP_CRQUERY:
         case OP_CRMINQUERY:          case OP_CRMINQUERY:
           case OP_CRPOSSTAR:
           case OP_CRPOSPLUS:
           case OP_CRPOSQUERY:
         c = *ecode++ - OP_CRSTAR;          c = *ecode++ - OP_CRSTAR;
        minimize = (c & 1) != 0;        if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0;
         else possessive = TRUE;
         min = rep_min[c];                 /* Pick up values from tables; */          min = rep_min[c];                 /* Pick up values from tables; */
         max = rep_max[c];                 /* zero for max => infinity */          max = rep_max[c];                 /* zero for max => infinity */
         if (max == 0) max = INT_MAX;          if (max == 0) max = INT_MAX;
Line 3060  for (;;) Line 3105  for (;;)
   
         case OP_CRRANGE:          case OP_CRRANGE:
         case OP_CRMINRANGE:          case OP_CRMINRANGE:
           case OP_CRPOSRANGE:
         minimize = (*ecode == OP_CRMINRANGE);          minimize = (*ecode == OP_CRMINRANGE);
           possessive = (*ecode == OP_CRPOSRANGE);
         min = GET2(ecode, 1);          min = GET2(ecode, 1);
         max = GET2(ecode, 1 + IMM2_SIZE);          max = GET2(ecode, 1 + IMM2_SIZE);
         if (max == 0) max = INT_MAX;          if (max == 0) max = INT_MAX;
Line 3132  for (;;) Line 3179  for (;;)
           if (!PRIV(xclass)(c, data, utf)) break;            if (!PRIV(xclass)(c, data, utf)) break;
           eptr += len;            eptr += len;
           }            }
   
           if (possessive) continue;    /* No backtracking */
   
         for(;;)          for(;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);
Line 3162  for (;;) Line 3212  for (;;)
         CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */          CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
         RRETURN(MATCH_NOMATCH);          RRETURN(MATCH_NOMATCH);
         }          }
      while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);      while (length-- > 0) if (*ecode++ != RAWUCHARINC(eptr)) RRETURN(MATCH_NOMATCH);
       }        }
     else      else
 #endif  #endif
Line 3202  for (;;) Line 3252  for (;;)
   
       if (fc < 128)        if (fc < 128)
         {          {
        if (md->lcc[fc]        pcre_uint32 cc = RAWUCHAR(eptr);
            != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH);        if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH);
         ecode++;          ecode++;
         eptr++;          eptr++;
         }          }
Line 3214  for (;;) Line 3264  for (;;)
   
       else        else
         {          {
        unsigned int dc;        pcre_uint32 dc;
         GETCHARINC(dc, eptr);          GETCHARINC(dc, eptr);
         ecode += length;          ecode += length;
   
Line 3307  for (;;) Line 3357  for (;;)
     max = rep_max[c];                 /* zero for max => infinity */      max = rep_max[c];                 /* zero for max => infinity */
     if (max == 0) max = INT_MAX;      if (max == 0) max = INT_MAX;
   
    /* Common code for all repeated single-character matches. */    /* Common code for all repeated single-character matches. We first check
     for the minimum number of characters. If the minimum equals the maximum, we
     are done. Otherwise, if minimizing, check the rest of the pattern for a
     match; if there isn't one, advance up to the maximum, one character at a
     time.
   
       If maximizing, advance up to the maximum number of matching characters,
       until eptr is past the end of the maximum run. If possessive, we are
       then 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. When we reach the first optional
       character position, we can save stack by doing a tail recurse.
   
       The various UTF/non-UTF and caseful/caseless cases are handled separately,
       for speed. */
   
     REPEATCHAR:      REPEATCHAR:
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
     if (utf)      if (utf)
Line 3324  for (;;) Line 3389  for (;;)
       if (length > 1)        if (length > 1)
         {          {
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
        unsigned int othercase;        pcre_uint32 othercase;
         if (op >= OP_STARI &&     /* Caseless */          if (op >= OP_STARI &&     /* Caseless */
             (othercase = UCD_OTHERCASE(fc)) != fc)              (othercase = UCD_OTHERCASE(fc)) != fc)
           oclength = PRIV(ord2utf)(othercase, occhars);            oclength = PRIV(ord2utf)(othercase, occhars);
Line 3391  for (;;) Line 3456  for (;;)
               }                }
             }              }
   
          if (possessive) continue;          if (possessive) continue;    /* No backtracking */
 
           for(;;)            for(;;)
             {              {
               if (eptr == pp) goto TAIL_RECURSE;
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (eptr == pp) { RRETURN(MATCH_NOMATCH); }  
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
             eptr--;              eptr--;
             BACKCHAR(eptr);              BACKCHAR(eptr);
Line 3451  for (;;) Line 3515  for (;;)
   
       for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
         {          {
           pcre_uint32 cc;                 /* Faster than pcre_uchar */
         if (eptr >= md->end_subject)          if (eptr >= md->end_subject)
           {            {
           SCHECK_PARTIAL();            SCHECK_PARTIAL();
           RRETURN(MATCH_NOMATCH);            RRETURN(MATCH_NOMATCH);
           }            }
        if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH);        cc = RAWUCHARTEST(eptr);
         if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
         eptr++;          eptr++;
         }          }
       if (min == max) continue;        if (min == max) continue;
Line 3464  for (;;) Line 3530  for (;;)
         {          {
         for (fi = min;; fi++)          for (fi = min;; fi++)
           {            {
             pcre_uint32 cc;               /* Faster than pcre_uchar */
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM24);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM24);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) RRETURN(MATCH_NOMATCH);            if (fi >= max) RRETURN(MATCH_NOMATCH);
Line 3472  for (;;) Line 3539  for (;;)
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH);          cc = RAWUCHARTEST(eptr);
           if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           }            }
         /* Control never gets here */          /* Control never gets here */
Line 3482  for (;;) Line 3550  for (;;)
         pp = eptr;          pp = eptr;
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
             pcre_uint32 cc;               /* Faster than pcre_uchar */
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             break;              break;
             }              }
          if (fc != *eptr && foc != *eptr) break;          cc = RAWUCHARTEST(eptr);
           if (fc != cc && foc != cc) break;
           eptr++;            eptr++;
           }            }
        if (possessive) continue;       /* No backtracking */
        if (possessive) continue;        for (;;)
 
        while (eptr >= pp) 
           {            {
             if (eptr == pp) goto TAIL_RECURSE;
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);
           eptr--;            eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }            }
        RRETURN(MATCH_NOMATCH);        /* Control never gets here */
         }          }
       /* Control never gets here */  
       }        }
   
     /* Caseful comparisons (includes all multi-byte characters) */      /* Caseful comparisons (includes all multi-byte characters) */
Line 3515  for (;;) Line 3583  for (;;)
           SCHECK_PARTIAL();            SCHECK_PARTIAL();
           RRETURN(MATCH_NOMATCH);            RRETURN(MATCH_NOMATCH);
           }            }
        if (fc != *eptr++) RRETURN(MATCH_NOMATCH);        if (fc != RAWUCHARINCTEST(eptr)) RRETURN(MATCH_NOMATCH);
         }          }
   
       if (min == max) continue;        if (min == max) continue;
Line 3532  for (;;) Line 3600  for (;;)
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (fc != *eptr++) RRETURN(MATCH_NOMATCH);          if (fc != RAWUCHARINCTEST(eptr)) RRETURN(MATCH_NOMATCH);
           }            }
         /* Control never gets here */          /* Control never gets here */
         }          }
Line 3546  for (;;) Line 3614  for (;;)
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             break;              break;
             }              }
          if (fc != *eptr) break;          if (fc != RAWUCHARTEST(eptr)) break;
           eptr++;            eptr++;
           }            }
        if (possessive) continue;        if (possessive) continue;    /* No backtracking */
        for (;;)
        while (eptr >= pp) 
           {            {
             if (eptr == pp) goto TAIL_RECURSE;
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);
           eptr--;            eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }            }
        RRETURN(MATCH_NOMATCH);        /* Control never gets here */
         }          }
       }        }
     /* Control never gets here */      /* Control never gets here */
Line 3575  for (;;) Line 3643  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
     if (utf)      if (utf)
       {        {
      register unsigned int ch, och;      register pcre_uint32 ch, och;
   
       ecode++;        ecode++;
       GETCHARINC(ch, ecode);        GETCHARINC(ch, ecode);
Line 3602  for (;;) Line 3670  for (;;)
     else      else
 #endif  #endif
       {        {
      register unsigned int ch = ecode[1];      register pcre_uint32 ch = ecode[1];
       c = *eptr++;        c = *eptr++;
       if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c))        if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c))
         RRETURN(MATCH_NOMATCH);          RRETURN(MATCH_NOMATCH);
Line 3716  for (;;) Line 3784  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
       if (utf)        if (utf)
         {          {
        register unsigned int d;        register pcre_uint32 d;
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
Line 3729  for (;;) Line 3797  for (;;)
           }            }
         }          }
       else        else
#endif#endif  /* SUPPORT_UTF */
       /* Not UTF mode */        /* Not UTF mode */
         {          {
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
Line 3751  for (;;) Line 3819  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
         if (utf)          if (utf)
           {            {
          register unsigned int d;          register pcre_uint32 d;
           for (fi = min;; fi++)            for (fi = min;; fi++)
             {              {
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM28);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM28);
Line 3767  for (;;) Line 3835  for (;;)
             }              }
           }            }
         else          else
#endif#endif  /*SUPPORT_UTF */
         /* Not UTF mode */          /* Not UTF mode */
           {            {
           for (fi = min;; fi++)            for (fi = min;; fi++)
Line 3796  for (;;) Line 3864  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
         if (utf)          if (utf)
           {            {
          register unsigned int d;          register pcre_uint32 d;
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
Line 3809  for (;;) Line 3877  for (;;)
             if (fc == d || (unsigned int)foc == d) break;              if (fc == d || (unsigned int)foc == d) break;
             eptr += len;              eptr += len;
             }              }
          if (possessive) continue;          if (possessive) continue;    /* No backtracking */
           for(;;)            for(;;)
             {              {
               if (eptr == pp) goto TAIL_RECURSE;
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr-- == pp) break;        /* Stop if tried at original pos */            eptr--;
             BACKCHAR(eptr);              BACKCHAR(eptr);
             }              }
           }            }
         else          else
#endif#endif  /* SUPPORT_UTF */
         /* Not UTF mode */          /* Not UTF mode */
           {            {
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
Line 3832  for (;;) Line 3901  for (;;)
             if (fc == *eptr || foc == *eptr) break;              if (fc == *eptr || foc == *eptr) break;
             eptr++;              eptr++;
             }              }
          if (possessive) continue;          if (possessive) continue;    /* No backtracking */
          while (eptr >= pp)          for (;;)
             {              {
               if (eptr == pp) goto TAIL_RECURSE;
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             eptr--;              eptr--;
             }              }
           }            }
        /* Control never gets here */
        RRETURN(MATCH_NOMATCH); 
         }          }
       /* Control never gets here */  
       }        }
   
     /* Caseful comparisons */      /* Caseful comparisons */
Line 3853  for (;;) Line 3921  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
       if (utf)        if (utf)
         {          {
        register unsigned int d;        register pcre_uint32 d;
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
Line 3887  for (;;) Line 3955  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
         if (utf)          if (utf)
           {            {
          register unsigned int d;          register pcre_uint32 d;
           for (fi = min;; fi++)            for (fi = min;; fi++)
             {              {
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM32);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM32);
Line 3931  for (;;) Line 3999  for (;;)
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
         if (utf)          if (utf)
           {            {
          register unsigned int d;          register pcre_uint32 d;
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
Line 3944  for (;;) Line 4012  for (;;)
             if (fc == d) break;              if (fc == d) break;
             eptr += len;              eptr += len;
             }              }
          if (possessive) continue;          if (possessive) continue;    /* No backtracking */
           for(;;)            for(;;)
             {              {
               if (eptr == pp) goto TAIL_RECURSE;
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr-- == pp) break;        /* Stop if tried at original pos */            eptr--;
             BACKCHAR(eptr);              BACKCHAR(eptr);
             }              }
           }            }
Line 3967  for (;;) Line 4036  for (;;)
             if (fc == *eptr) break;              if (fc == *eptr) break;
             eptr++;              eptr++;
             }              }
          if (possessive) continue;          if (possessive) continue;    /* No backtracking */
          while (eptr >= pp)          for (;;)
             {              {
               if (eptr == pp) goto TAIL_RECURSE;
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);              RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             eptr--;              eptr--;
             }              }
           }            }
        /* Control never gets here */
        RRETURN(MATCH_NOMATCH); 
         }          }
       }        }
     /* Control never gets here */      /* Control never gets here */
Line 4158  for (;;) Line 4227  for (;;)
             }              }
           break;            break;
   
             /* Perl space used to exclude VT, but from Perl 5.18 it is included,
             which means that Perl space and POSIX space are now identical. PCRE
             was changed at release 8.34. */
   
           case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
             case PT_PXSPACE:  /* POSIX space */
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
Line 4167  for (;;) Line 4241  for (;;)
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||            switch(c)
                 c == CHAR_FF || c == CHAR_CR)              {
                   == prop_fail_result)              HSPACE_CASES:
              RRETURN(MATCH_NOMATCH);              VSPACE_CASES:
               if (prop_fail_result) RRETURN(MATCH_NOMATCH);
               break;
 
               default:
               if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
                 RRETURN(MATCH_NOMATCH);
               break;
               }
             }              }
           break;            break;
   
          case PT_PXSPACE:  /* POSIX space */          case PT_WORD:
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
               int category;
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
               {                {
               SCHECK_PARTIAL();                SCHECK_PARTIAL();
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||            category = UCD_CATEGORY(c);
                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)            if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE)
                    == prop_fail_result)                     == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
             }              }
           break;            break;
   
          case PT_WORD:          case PT_CLIST:
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
            int category;            const pcre_uint32 *cp;
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
               {                {
               SCHECK_PARTIAL();                SCHECK_PARTIAL();
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
            category = UCD_CATEGORY(c);            cp = PRIV(ucd_caseless_sets) + prop_value;
            if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE)            for (;;)
                   == prop_fail_result)              {
               if (c < *cp)
                 { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } }
               if (c == *cp++)
                 { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; }
               }
             }
           break;
 
           case PT_UCNC:
           for (i = 1; i <= min; i++)
             {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
                    c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
                    c >= 0xe000) == prop_fail_result)
                 RRETURN(MATCH_NOMATCH);
             }              }
           break;            break;
   
Line 4226  for (;;) Line 4329  for (;;)
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          GETCHARINCTEST(c, eptr);          else
          if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); 
          while (eptr < md->end_subject) 
             {              {
            int len = 1;            int lgb, rgb;
            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }            GETCHARINCTEST(c, eptr);
            if (UCD_CATEGORY(c) != ucp_M) break;            lgb = UCD_GRAPHBREAK(c);
            eptr += len;           while (eptr < md->end_subject)
               {
               int len = 1;
               if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
               rgb = UCD_GRAPHBREAK(c);
               if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
               lgb = rgb;
               eptr += len;
               }
             }              }
           CHECK_PARTIAL();            CHECK_PARTIAL();
           }            }
Line 4260  for (;;) Line 4369  for (;;)
               eptr + 1 >= md->end_subject &&                eptr + 1 >= md->end_subject &&
               NLBLOCK->nltype == NLTYPE_FIXED &&                NLBLOCK->nltype == NLTYPE_FIXED &&
               NLBLOCK->nllen == 2 &&                NLBLOCK->nllen == 2 &&
              *eptr == NLBLOCK->nl[0])              RAWUCHAR(eptr) == NLBLOCK->nl[0])
             {              {
             md->hitend = TRUE;              md->hitend = TRUE;
             if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);              if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
Line 4301  for (;;) Line 4410  for (;;)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
   
            case 0x000d:            case CHAR_CR:
            if (eptr < md->end_subject && *eptr == 0x0a) eptr++;            if (eptr < md->end_subject && RAWUCHAR(eptr) == CHAR_LF) eptr++;
             break;              break;
   
            case 0x000a:            case CHAR_LF:
             break;              break;
   
            case 0x000b:            case CHAR_VT:
            case 0x000c:            case CHAR_FF:
            case 0x0085:            case CHAR_NEL:
 #ifndef EBCDIC
             case 0x2028:              case 0x2028:
             case 0x2029:              case 0x2029:
   #endif  /* Not EBCDIC */
             if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
             break;              break;
             }              }
Line 4330  for (;;) Line 4441  for (;;)
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
               HSPACE_CASES: RRETURN(MATCH_NOMATCH);  /* Byte and multibyte cases */
             default: break;              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;          break;
Line 4366  for (;;) Line 4458  for (;;)
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
               HSPACE_CASES: break;  /* Byte and multibyte cases */
             default: RRETURN(MATCH_NOMATCH);              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;          break;
Line 4402  for (;;) Line 4475  for (;;)
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
               VSPACE_CASES: RRETURN(MATCH_NOMATCH);
             default: break;              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;          break;
Line 4426  for (;;) Line 4492  for (;;)
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
               VSPACE_CASES: break;
             default: RRETURN(MATCH_NOMATCH);              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;          break;
Line 4456  for (;;) Line 4515  for (;;)
         case OP_DIGIT:          case OP_DIGIT:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             pcre_uint32 cc;
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_digit) == 0)          cc = RAWUCHAR(eptr);
           if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0)
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           /* No need to skip more bytes - we know it's a 1-byte character */            /* No need to skip more bytes - we know it's a 1-byte character */
Line 4471  for (;;) Line 4532  for (;;)
         case OP_NOT_WHITESPACE:          case OP_NOT_WHITESPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             pcre_uint32 cc;
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)          cc = RAWUCHAR(eptr);
           if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0)
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);            ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
Line 4486  for (;;) Line 4549  for (;;)
         case OP_WHITESPACE:          case OP_WHITESPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             pcre_uint32 cc;
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_space) == 0)          cc = RAWUCHAR(eptr);
           if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0)
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           /* No need to skip more bytes - we know it's a 1-byte character */            /* No need to skip more bytes - we know it's a 1-byte character */
Line 4501  for (;;) Line 4566  for (;;)
         case OP_NOT_WORDCHAR:          case OP_NOT_WORDCHAR:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             pcre_uint32 cc;
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0)          cc = RAWUCHAR(eptr);
           if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0)
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);            ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
Line 4516  for (;;) Line 4583  for (;;)
         case OP_WORDCHAR:          case OP_WORDCHAR:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             pcre_uint32 cc;
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_word) == 0)          cc = RAWUCHAR(eptr);
           if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0)
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           /* No need to skip more bytes - we know it's a 1-byte character */            /* No need to skip more bytes - we know it's a 1-byte character */
Line 4592  for (;;) Line 4661  for (;;)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
   
            case 0x000d:            case CHAR_CR:
            if (eptr < md->end_subject && *eptr == 0x0a) eptr++;            if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
             break;              break;
   
            case 0x000a:            case CHAR_LF:
             break;              break;
   
            case 0x000b:            case CHAR_VT:
            case 0x000c:            case CHAR_FF:
            case 0x0085:            case CHAR_NEL:
#ifdef COMPILE_PCRE16#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
             case 0x2028:              case 0x2028:
             case 0x2029:              case 0x2029:
 #endif  #endif
Line 4623  for (;;) Line 4692  for (;;)
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: break;              default: break;
            case 0x09:      /* HT */            HSPACE_BYTE_CASES:
            case 0x20:      /* SPACE */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
            case 0xa0:      /* NBSP */            HSPACE_MULTIBYTE_CASES:
#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  #endif
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
Line 4660  for (;;) Line 4712  for (;;)
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
            case 0x09:      /* HT */            HSPACE_BYTE_CASES:
            case 0x20:      /* SPACE */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
            case 0xa0:      /* NBSP */            HSPACE_MULTIBYTE_CASES:
#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  #endif
             break;              break;
             }              }
Line 4696  for (;;) Line 4731  for (;;)
             }              }
           switch(*eptr++)            switch(*eptr++)
             {              {
            default: break;            VSPACE_BYTE_CASES:
            case 0x0a:      /* LF */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
            case 0x0b:      /* VT */            VSPACE_MULTIBYTE_CASES:
            case 0x0c:      /* FF */ 
            case 0x0d:      /* CR */ 
            case 0x85:      /* NEL */ 
#ifdef COMPILE_PCRE16 
            case 0x2028:    /* LINE SEPARATOR */ 
            case 0x2029:    /* PARAGRAPH SEPARATOR */ 
 #endif  #endif
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
               default: break;
             }              }
           }            }
         break;          break;
Line 4722  for (;;) Line 4752  for (;;)
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
            case 0x0a:      /* LF */            VSPACE_BYTE_CASES:
            case 0x0b:      /* VT */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
            case 0x0c:      /* FF */            VSPACE_MULTIBYTE_CASES:
            case 0x0d:      /* CR */ 
            case 0x85:      /* NEL */ 
#ifdef COMPILE_PCRE16 
            case 0x2028:    /* LINE SEPARATOR */ 
            case 0x2029:    /* PARAGRAPH SEPARATOR */ 
 #endif  #endif
             break;              break;
             }              }
Line 4947  for (;;) Line 4972  for (;;)
             }              }
           /* Control never gets here */            /* Control never gets here */
   
             /* Perl space used to exclude VT, but from Perl 5.18 it is included,
             which means that Perl space and POSIX space are now identical. PCRE
             was changed at release 8.34. */
   
           case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
             case PT_PXSPACE:  /* POSIX space */
           for (fi = min;; fi++)            for (fi = min;; fi++)
             {              {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM60);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM61);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
Line 4959  for (;;) Line 4989  for (;;)
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||            switch(c)
                 c == CHAR_FF || c == CHAR_CR)              {
                   == prop_fail_result)              HSPACE_CASES:
              RRETURN(MATCH_NOMATCH);              VSPACE_CASES:
               if (prop_fail_result) RRETURN(MATCH_NOMATCH);
               break;
 
               default:
               if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
                 RRETURN(MATCH_NOMATCH);
               break;
               }
             }              }
           /* Control never gets here */            /* Control never gets here */
   
          case PT_PXSPACE:  /* POSIX space */          case PT_WORD:
           for (fi = min;; fi++)            for (fi = min;; fi++)
             {              {
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM61);            int category;
             RMATCH(eptr, ecode, offset_top, md, eptrb, RM62);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
Line 4978  for (;;) Line 5017  for (;;)
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||            category = UCD_CATEGORY(c);
                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)            if ((category == ucp_L ||
                  category == ucp_N ||
                  c == CHAR_UNDERSCORE)
                    == prop_fail_result)                     == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
          case PT_WORD:          case PT_CLIST:
           for (fi = min;; fi++)            for (fi = min;; fi++)
             {              {
            int category;            const pcre_uint32 *cp;
            RMATCH(eptr, ecode, offset_top, md, eptrb, RM62);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM67);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
Line 4998  for (;;) Line 5039  for (;;)
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
            category = UCD_CATEGORY(c);            cp = PRIV(ucd_caseless_sets) + prop_value;
            if ((category == ucp_L ||            for (;;)
                 category == ucp_N ||              {
                 c == CHAR_UNDERSCORE)              if (c < *cp)
                   == prop_fail_result)                { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } }
               if (c == *cp++)
                 { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; }
               }
             }
           /* Control never gets here */
 
           case PT_UCNC:
           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);                RRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
                    c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
                    c >= 0xe000) == prop_fail_result)
                 RRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
           /* This should never occur */            /* This should never occur */
   
           default:            default:
           RRETURN(PCRE_ERROR_INTERNAL);            RRETURN(PCRE_ERROR_INTERNAL);
           }            }
Line 5029  for (;;) Line 5090  for (;;)
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
             }              }
          GETCHARINCTEST(c, eptr);          else
          if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); 
          while (eptr < md->end_subject) 
             {              {
            int len = 1;            int lgb, rgb;
            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }            GETCHARINCTEST(c, eptr);
            if (UCD_CATEGORY(c) != ucp_M) break;            lgb = UCD_GRAPHBREAK(c);
            eptr += len;            while (eptr < md->end_subject)
               {
               int len = 1;
               if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
               rgb = UCD_GRAPHBREAK(c);
               if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
               lgb = rgb;
               eptr += len;
               }
             }              }
           CHECK_PARTIAL();            CHECK_PARTIAL();
           }            }
Line 5082  for (;;) Line 5149  for (;;)
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: RRETURN(MATCH_NOMATCH);
              case 0x000d:              case CHAR_CR:
              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;              if (eptr < md->end_subject && RAWUCHAR(eptr) == CHAR_LF) eptr++;
               break;                break;
              case 0x000a:
               case CHAR_LF:
               break;                break;
   
              case 0x000b:              case CHAR_VT:
              case 0x000c:              case CHAR_FF:
              case 0x0085:              case CHAR_NEL:
 #ifndef EBCDIC
               case 0x2028:                case 0x2028:
               case 0x2029:                case 0x2029:
   #endif  /* Not EBCDIC */
               if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);                if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
               break;                break;
               }                }
Line 5101  for (;;) Line 5171  for (;;)
             case OP_NOT_HSPACE:              case OP_NOT_HSPACE:
             switch(c)              switch(c)
               {                {
                 HSPACE_CASES: RRETURN(MATCH_NOMATCH);
               default: break;                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;              break;
   
             case OP_HSPACE:              case OP_HSPACE:
             switch(c)              switch(c)
               {                {
                 HSPACE_CASES: break;
               default: RRETURN(MATCH_NOMATCH);                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;              break;
   
             case OP_NOT_VSPACE:              case OP_NOT_VSPACE:
             switch(c)              switch(c)
               {                {
                 VSPACE_CASES: RRETURN(MATCH_NOMATCH);
               default: break;                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;              break;
   
             case OP_VSPACE:              case OP_VSPACE:
             switch(c)              switch(c)
               {                {
                 VSPACE_CASES: break;
               default: RRETURN(MATCH_NOMATCH);                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;              break;
   
Line 5256  for (;;) Line 5274  for (;;)
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: RRETURN(MATCH_NOMATCH);
              case 0x000d:              case CHAR_CR:
              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;              if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
               break;                break;
   
              case 0x000a:              case CHAR_LF:
               break;                break;
   
              case 0x000b:              case CHAR_VT:
              case 0x000c:              case CHAR_FF:
              case 0x0085:              case CHAR_NEL:
#ifdef COMPILE_PCRE16#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
               case 0x2028:                case 0x2028:
               case 0x2029:                case 0x2029:
 #endif  #endif
Line 5279  for (;;) Line 5297  for (;;)
             switch(c)              switch(c)
               {                {
               default: break;                default: break;
              case 0x09:      /* HT */              HSPACE_BYTE_CASES:
              case 0x20:      /* SPACE */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
              case 0xa0:      /* NBSP */              HSPACE_MULTIBYTE_CASES:
#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  #endif
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
Line 5308  for (;;) Line 5309  for (;;)
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: RRETURN(MATCH_NOMATCH);
              case 0x09:      /* HT */              HSPACE_BYTE_CASES:
              case 0x20:      /* SPACE */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
              case 0xa0:      /* NBSP */              HSPACE_MULTIBYTE_CASES:
#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  #endif
               break;                break;
               }                }
Line 5337  for (;;) Line 5321  for (;;)
             switch(c)              switch(c)
               {                {
               default: break;                default: break;
              case 0x0a:      /* LF */              VSPACE_BYTE_CASES:
              case 0x0b:      /* VT */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
              case 0x0c:      /* FF */              VSPACE_MULTIBYTE_CASES:
              case 0x0d:      /* CR */ 
              case 0x85:      /* NEL */ 
#ifdef COMPILE_PCRE16 
              case 0x2028:    /* LINE SEPARATOR */ 
              case 0x2029:    /* PARAGRAPH SEPARATOR */ 
 #endif  #endif
               RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
               }                }
Line 5354  for (;;) Line 5333  for (;;)
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: RRETURN(MATCH_NOMATCH);
              case 0x0a:      /* LF */              VSPACE_BYTE_CASES:
              case 0x0b:      /* VT */#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
              case 0x0c:      /* FF */              VSPACE_MULTIBYTE_CASES:
              case 0x0d:      /* CR */ 
              case 0x85:      /* NEL */ 
#ifdef COMPILE_PCRE16 
              case 0x2028:    /* LINE SEPARATOR */ 
              case 0x2029:    /* PARAGRAPH SEPARATOR */ 
 #endif  #endif
               break;                break;
               }                }
Line 5510  for (;;) Line 5484  for (;;)
             }              }
           break;            break;
   
             /* Perl space used to exclude VT, but from Perl 5.18 it is included,
             which means that Perl space and POSIX space are now identical. PCRE
             was changed at release 8.34. */
   
           case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
             case PT_PXSPACE:  /* POSIX space */
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
Line 5520  for (;;) Line 5499  for (;;)
               break;                break;
               }                }
             GETCHARLENTEST(c, eptr, len);              GETCHARLENTEST(c, eptr, len);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||            switch(c)
                 c == CHAR_FF || c == CHAR_CR)              {
                 == prop_fail_result)              HSPACE_CASES:
               VSPACE_CASES:
               if (prop_fail_result) goto ENDLOOP99;  /* Break the loop */
               break;                break;
   
                 default:
                 if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
                   goto ENDLOOP99;   /* Break the loop */
                 break;
                 }
             eptr+= len;              eptr+= len;
             }              }
             ENDLOOP99:
           break;            break;
   
          case PT_PXSPACE:  /* POSIX space */          case PT_WORD:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
               int category;
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
               {                {
Line 5538  for (;;) Line 5527  for (;;)
               break;                break;
               }                }
             GETCHARLENTEST(c, eptr, len);              GETCHARLENTEST(c, eptr, len);
            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||            category = UCD_CATEGORY(c);
                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)            if ((category == ucp_L || category == ucp_N ||
                 == prop_fail_result)                 c == CHAR_UNDERSCORE) == prop_fail_result)
               break;                break;
             eptr+= len;              eptr+= len;
             }              }
           break;            break;
   
          case PT_WORD:          case PT_CLIST:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
            int category;            const pcre_uint32 *cp;
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject)              if (eptr >= md->end_subject)
               {                {
Line 5557  for (;;) Line 5546  for (;;)
               break;                break;
               }                }
             GETCHARLENTEST(c, eptr, len);              GETCHARLENTEST(c, eptr, len);
            category = UCD_CATEGORY(c);            cp = PRIV(ucd_caseless_sets) + prop_value;
            if ((category == ucp_L || category == ucp_N ||            for (;;)
                 c == CHAR_UNDERSCORE) == prop_fail_result)              {
               if (c < *cp)
                 { if (prop_fail_result) break; else goto GOT_MAX; }
               if (c == *cp++)
                 { if (prop_fail_result) goto GOT_MAX; else break; }
               }
             eptr += len;
             }
           GOT_MAX:
           break;
 
           case PT_UCNC:
           for (i = min; i < max; i++)
             {
             int len = 1;
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               break;                break;
            eptr+= len;              }
             GETCHARLENTEST(c, eptr, len);
             if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
                  c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
                  c >= 0xe000) == prop_fail_result)
               break;
             eptr += len;
             }              }
           break;            break;
   
Line 5571  for (;;) Line 5583  for (;;)
   
         /* eptr is now past the end of the maximum run */          /* eptr is now past the end of the maximum run */
   
        if (possessive) continue;        if (possessive) continue;    /* No backtracking */
         for(;;)          for(;;)
           {            {
             if (eptr == pp) goto TAIL_RECURSE;
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */          eptr--;
           if (utf) BACKCHAR(eptr);            if (utf) BACKCHAR(eptr);
           }            }
         }          }
   
      /* Match extended Unicode sequences. We will get here only if the      /* Match extended Unicode grapheme clusters. We will get here only if the
       support is in the binary; otherwise a compile-time error occurs. */        support is in the binary; otherwise a compile-time error occurs. */
   
       else if (ctype == OP_EXTUNI)        else if (ctype == OP_EXTUNI)
         {          {
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
           int len = 1;  
           if (eptr >= md->end_subject)            if (eptr >= md->end_subject)
             {              {
             SCHECK_PARTIAL();              SCHECK_PARTIAL();
             break;              break;
             }              }
          if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }          else
          if (UCD_CATEGORY(c) == ucp_M) break; 
          eptr += len; 
          while (eptr < md->end_subject) 
             {              {
            len = 1;            int lgb, rgb;
            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }            GETCHARINCTEST(c, eptr);
            if (UCD_CATEGORY(c) != ucp_M) break;            lgb = UCD_GRAPHBREAK(c);
            eptr += len;            while (eptr < md->end_subject)
               {
               int len = 1;
               if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
               rgb = UCD_GRAPHBREAK(c);
               if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
               lgb = rgb;
               eptr += len;
               }
             }              }
           CHECK_PARTIAL();            CHECK_PARTIAL();
           }            }
   
         /* eptr is now past the end of the maximum run */          /* eptr is now past the end of the maximum run */
   
        if (possessive) continue;        if (possessive) continue;    /* No backtracking */
   
         for(;;)          for(;;)
           {            {
             int lgb, rgb;
             PCRE_PUCHAR fptr;
   
             if (eptr == pp) goto TAIL_RECURSE;   /* At start of char run */
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */
          for (;;)                        /* Move back over one extended */          /* Backtracking over an extended grapheme cluster involves inspecting
           the previous two characters (if present) to see if a break is
           permitted between them. */
 
           eptr--;
           if (!utf) c = *eptr; else
             {              {
            if (!utf) c = *eptr; else            BACKCHAR(eptr);
             GETCHAR(c, eptr);
             }
           rgb = UCD_GRAPHBREAK(c);
 
           for (;;)
             {
             if (eptr == pp) goto TAIL_RECURSE;   /* At start of char run */
             fptr = eptr - 1;
             if (!utf) c = *fptr; else
               {                {
              BACKCHAR(eptr);              BACKCHAR(fptr);
              GETCHAR(c, eptr);              GETCHAR(c, fptr);
               }                }
            if (UCD_CATEGORY(c) != ucp_M) break;            lgb = UCD_GRAPHBREAK(c);
            eptr--;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
             eptr = fptr;
             rgb = lgb;
             }              }
           }            }
         }          }
Line 5652  for (;;) Line 5689  for (;;)
                   eptr + 1 >= md->end_subject &&                    eptr + 1 >= md->end_subject &&
                   NLBLOCK->nltype == NLTYPE_FIXED &&                    NLBLOCK->nltype == NLTYPE_FIXED &&
                   NLBLOCK->nllen == 2 &&                    NLBLOCK->nllen == 2 &&
                  *eptr == NLBLOCK->nl[0])                  RAWUCHAR(eptr) == NLBLOCK->nl[0])
                 {                  {
                 md->hitend = TRUE;                  md->hitend = TRUE;
                 if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);                  if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
Line 5678  for (;;) Line 5715  for (;;)
                   eptr + 1 >= md->end_subject &&                    eptr + 1 >= md->end_subject &&
                   NLBLOCK->nltype == NLTYPE_FIXED &&                    NLBLOCK->nltype == NLTYPE_FIXED &&
                   NLBLOCK->nllen == 2 &&                    NLBLOCK->nllen == 2 &&
                  *eptr == NLBLOCK->nl[0])                  RAWUCHAR(eptr) == NLBLOCK->nl[0])
                 {                  {
                 md->hitend = TRUE;                  md->hitend = TRUE;
                 if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);                  if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
Line 5732  for (;;) Line 5769  for (;;)
               break;                break;
               }                }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
            if (c == 0x000d)            if (c == CHAR_CR)
               {                {
               if (++eptr >= md->end_subject) break;                if (++eptr >= md->end_subject) break;
              if (*eptr == 0x000a) eptr++;              if (RAWUCHAR(eptr) == CHAR_LF) eptr++;
               }                }
             else              else
               {                {
              if (c != 0x000a &&              if (c != CHAR_LF &&
                   (md->bsr_anycrlf ||                    (md->bsr_anycrlf ||
                   (c != 0x000b && c != 0x000c &&                   (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
                    c != 0x0085 && c != 0x2028 && c != 0x2029)))#ifndef EBCDIC
                     && c != 0x2028 && c != 0x2029
 #endif  /* Not EBCDIC */
                     )))
                 break;                  break;
               eptr += len;                eptr += len;
               }                }
Line 5763  for (;;) Line 5803  for (;;)
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             switch(c)              switch(c)
               {                {
                 HSPACE_CASES: gotspace = TRUE; break;
               default: gotspace = FALSE; break;                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;              if (gotspace == (ctype == OP_NOT_HSPACE)) break;
             eptr += len;              eptr += len;
Line 5805  for (;;) Line 5825  for (;;)
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             switch(c)              switch(c)
               {                {
                 VSPACE_CASES: gotspace = TRUE; break;
               default: gotspace = FALSE; break;                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;              if (gotspace == (ctype == OP_NOT_VSPACE)) break;
             eptr += len;              eptr += len;
Line 5915  for (;;) Line 5927  for (;;)
           RRETURN(PCRE_ERROR_INTERNAL);            RRETURN(PCRE_ERROR_INTERNAL);
           }            }
   
        /* eptr is now past the end of the maximum run. If possessive, we are        if (possessive) continue;    /* No backtracking */
        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(;;)          for(;;)
           {            {
             if (eptr == pp) goto TAIL_RECURSE;
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
          if (eptr-- == pp) break;        /* Stop if tried at original pos */          eptr--;
           BACKCHAR(eptr);            BACKCHAR(eptr);
          if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' &&          if (ctype == OP_ANYNL && eptr > pp  && RAWUCHAR(eptr) == CHAR_NL &&
              eptr[-1] == '\r') eptr--;              RAWUCHAR(eptr - 1) == CHAR_CR) eptr--;
           }            }
         }          }
       else        else
Line 5980  for (;;) Line 5987  for (;;)
               break;                break;
               }                }
             c = *eptr;              c = *eptr;
            if (c == 0x000d)            if (c == CHAR_CR)
               {                {
               if (++eptr >= md->end_subject) break;                if (++eptr >= md->end_subject) break;
              if (*eptr == 0x000a) eptr++;              if (*eptr == CHAR_LF) eptr++;
               }                }
             else              else
               {                {
              if (c != 0x000a && (md->bsr_anycrlf ||              if (c != CHAR_LF && (md->bsr_anycrlf ||
                (c != 0x000b && c != 0x000c && c != 0x0085                 (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
#ifdef COMPILE_PCRE16#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
                && c != 0x2028 && c != 0x2029                 && c != 0x2028 && c != 0x2029
 #endif  #endif
                ))) break;                 ))) break;
               eptr++;                eptr++;
               }                }
             }              }
Line 6006  for (;;) Line 6013  for (;;)
               SCHECK_PARTIAL();                SCHECK_PARTIAL();
               break;                break;
               }                }
            c = *eptr;            switch(*eptr)
            if (c == 0x09 || c == 0x20 || c == 0xa0              {
#ifdef COMPILE_PCRE16              default: eptr++; break;
              || c == 0x1680 || c == 0x180e || (c >= 0x2000 && c <= 0x200A)              HSPACE_BYTE_CASES:
              || c == 0x202f || c == 0x205f || c == 0x3000#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
               HSPACE_MULTIBYTE_CASES:
 #endif  #endif
              ) break;              goto ENDLOOP00;
            eptr++;              }
             }              }
             ENDLOOP00:
           break;            break;
   
           case OP_HSPACE:            case OP_HSPACE:
Line 6025  for (;;) Line 6034  for (;;)
               SCHECK_PARTIAL();                SCHECK_PARTIAL();
               break;                break;
               }                }
            c = *eptr;            switch(*eptr)
            if (c != 0x09 && c != 0x20 && c != 0xa0              {
#ifdef COMPILE_PCRE16              default: goto ENDLOOP01;
              && c != 0x1680 && c != 0x180e && (c < 0x2000 || c > 0x200A)              HSPACE_BYTE_CASES:
              && c != 0x202f && c != 0x205f && c != 0x3000#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
               HSPACE_MULTIBYTE_CASES:
 #endif  #endif
              ) break;              eptr++; break;
            eptr++;              }
             }              }
             ENDLOOP01:
           break;            break;
   
           case OP_NOT_VSPACE:            case OP_NOT_VSPACE:
Line 6044  for (;;) Line 6055  for (;;)
               SCHECK_PARTIAL();                SCHECK_PARTIAL();
               break;                break;
               }                }
            c = *eptr;            switch(*eptr)
            if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85              {
#ifdef COMPILE_PCRE16              default: eptr++; break;
              || c == 0x2028 || c == 0x2029              VSPACE_BYTE_CASES:
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
               VSPACE_MULTIBYTE_CASES:
 #endif  #endif
              ) break;              goto ENDLOOP02;
            eptr++;              }
             }              }
             ENDLOOP02:
           break;            break;
   
           case OP_VSPACE:            case OP_VSPACE:
Line 6062  for (;;) Line 6076  for (;;)
               SCHECK_PARTIAL();                SCHECK_PARTIAL();
               break;                break;
               }                }
            c = *eptr;            switch(*eptr)
            if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85              {
#ifdef COMPILE_PCRE16              default: goto ENDLOOP03;
              && c != 0x2028 && c != 0x2029              VSPACE_BYTE_CASES:
 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
               VSPACE_MULTIBYTE_CASES:
 #endif  #endif
              ) break;              eptr++; break;
            eptr++;              }
             }              }
             ENDLOOP03:
           break;            break;
   
           case OP_NOT_DIGIT:            case OP_NOT_DIGIT:
Line 6154  for (;;) Line 6171  for (;;)
           RRETURN(PCRE_ERROR_INTERNAL);            RRETURN(PCRE_ERROR_INTERNAL);
           }            }
   
        /* eptr is now past the end of the maximum run. If possessive, we are        if (possessive) continue;    /* No backtracking */
        done (no backing up). Otherwise, match at this position; anything other        for (;;)
        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) 
           {            {
             if (eptr == pp) goto TAIL_RECURSE;
           RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);            RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           eptr--;            eptr--;
          if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' &&          if (ctype == OP_ANYNL && eptr > pp  && *eptr == CHAR_LF &&
              eptr[-1] == '\r') eptr--;              eptr[-1] == CHAR_CR) eptr--;
           }            }
         }          }
   
      /* Get here if we can't make it match with any permitted repetitions */      /* Control never gets here */
 
      RRETURN(MATCH_NOMATCH); 
       }        }
     /* Control never gets here */  
   
     /* There's been some horrible disaster. Arrival here can only mean there is      /* 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. */      something seriously wrong in the code above or the OP_xxx definitions. */
Line 6209  switch (frame->Xwhere) Line 6218  switch (frame->Xwhere)
   LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64)    LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64)
   LBL(65) LBL(66)    LBL(65) LBL(66)
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
  LBL(21)  LBL(20) LBL(21)
 #endif  #endif
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
  LBL(16) LBL(18) LBL(20)  LBL(16) LBL(18)
   LBL(22) LBL(23) LBL(28) LBL(30)    LBL(22) LBL(23) LBL(28) LBL(30)
   LBL(32) LBL(34) LBL(42) LBL(46)    LBL(32) LBL(34) LBL(42) LBL(46)
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
   LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)    LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)
  LBL(59) LBL(60) LBL(61) LBL(62)  LBL(59) LBL(60) LBL(61) LBL(62) LBL(67)
 #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
 #endif  /* SUPPORT_UTF */  #endif  /* SUPPORT_UTF */
   default:    default:
   DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));    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;    return PCRE_ERROR_INTERNAL;
   }    }
 #undef LBL  #undef LBL
Line 6336  Returns:          > 0 => success; value is the number  Line 6342  Returns:          > 0 => success; value is the number 
                  < -1 => some kind of unexpected problem                   < -1 => some kind of unexpected problem
 */  */
   
#ifdef COMPILE_PCRE8#if defined COMPILE_PCRE8
 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
 pcre_exec(const pcre *argument_re, const pcre_extra *extra_data,  pcre_exec(const pcre *argument_re, const pcre_extra *extra_data,
   PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,    PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
   int offsetcount)    int offsetcount)
#else#elif defined COMPILE_PCRE16
 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
 pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,  pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
   PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,    PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
   int offsetcount)    int offsetcount)
   #elif defined COMPILE_PCRE32
   PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
   pcre32_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
     PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
     int offsetcount)
 #endif  #endif
 {  {
 int rc, ocount, arg_offset_max;  int rc, ocount, arg_offset_max;
Line 6368  const pcre_uint8 *start_bits = NULL; Line 6379  const pcre_uint8 *start_bits = NULL;
 PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset;  PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset;
 PCRE_PUCHAR end_subject;  PCRE_PUCHAR end_subject;
 PCRE_PUCHAR start_partial = NULL;  PCRE_PUCHAR start_partial = NULL;
   PCRE_PUCHAR match_partial = NULL;
 PCRE_PUCHAR req_char_ptr = start_match - 1;  PCRE_PUCHAR req_char_ptr = start_match - 1;
   
 const pcre_study_data *study;  const pcre_study_data *study;
Line 6399  if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE Line 6411  if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE
 if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0))  if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0))
   return PCRE_ERROR_NULL;    return PCRE_ERROR_NULL;
 if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;  if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
   if (length < 0) return PCRE_ERROR_BADLENGTH;
 if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;  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,  /* Check that the first field in the block is the magic number. If it is not,
Line 6436  if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) Line 6449  if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
       offsets[0] = erroroffset;        offsets[0] = erroroffset;
       offsets[1] = errorcode;        offsets[1] = errorcode;
       }        }
#ifdef COMPILE_PCRE16#if defined COMPILE_PCRE8
    return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)? 
      PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16; 
#else 
     return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?      return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?
       PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;        PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
   #elif defined COMPILE_PCRE16
       return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)?
         PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
   #elif defined COMPILE_PCRE32
       return PCRE_ERROR_BADUTF32;
 #endif  #endif
     }      }
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
   /* Check that a start_offset points to the start of a UTF character. */    /* Check that a start_offset points to the start of a UTF character. */
   if (start_offset > 0 && start_offset < length &&    if (start_offset > 0 && start_offset < length &&
       NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))        NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
     return PCRE_ERROR_BADUTF8_OFFSET;      return PCRE_ERROR_BADUTF8_OFFSET;
   #endif
   }    }
 #endif  #endif
   
Line 6462  if (extra_data != NULL Line 6478  if (extra_data != NULL
     && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT |      && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT |
                              PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT                               PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT
     && extra_data->executable_jit != NULL      && extra_data->executable_jit != NULL
    && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL |    && (options & ~PUBLIC_JIT_EXEC_OPTIONS) == 0)
                    PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | 
                    PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD)) == 0) 
   {    {
  rc = PRIV(jit_exec)(re, extra_data, (const pcre_uchar *)subject, length,  rc = PRIV(jit_exec)(extra_data, (const pcre_uchar *)subject, length,
        start_offset, options, offsets, offsetcount);         start_offset, options, offsets, offsetcount);
   
   /* PCRE_ERROR_NULL means that the selected normal or partial matching    /* PCRE_ERROR_NULL means that the selected normal or partial matching
   mode is not compiled. In this case we simply fallback to interpreter. */    mode is not compiled. In this case we simply fallback to interpreter. */
   
  if (rc != PCRE_ERROR_NULL) return rc;  if (rc != PCRE_ERROR_JIT_BADOPTION) return rc;
   }    }
 #endif  #endif
   
Line 6495  md->callout_data = NULL; Line 6509  md->callout_data = NULL;
   
 tables = re->tables;  tables = re->tables;
   
   /* The two limit values override the defaults, whatever their value. */
   
 if (extra_data != NULL)  if (extra_data != NULL)
   {    {
   register unsigned int flags = extra_data->flags;    register unsigned int flags = extra_data->flags;
Line 6509  if (extra_data != NULL) Line 6525  if (extra_data != NULL)
   if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;    if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;
   }    }
   
   /* Limits in the regex override only if they are smaller. */
   
   if ((re->flags & PCRE_MLSET) != 0 && re->limit_match < md->match_limit)
     md->match_limit = re->limit_match;
   
   if ((re->flags & PCRE_RLSET) != 0 &&
       re->limit_recursion < md->match_limit_recursion)
     md->match_limit_recursion = re->limit_recursion;
   
 /* If the exec call supplied NULL for tables, use the inbuilt ones. This  /* 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  is a feature that makes it possible to save compiled regex and re-use them
 in other programs later. */  in other programs later. */
Line 6534  end_subject = md->end_subject; Line 6559  end_subject = md->end_subject;
 md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;  md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
 md->use_ucp = (re->options & PCRE_UCP) != 0;  md->use_ucp = (re->options & PCRE_UCP) != 0;
 md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;  md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
md->ignore_skip_arg = FALSE;md->ignore_skip_arg = 0;
   
 /* Some options are unpacked into BOOL variables in the hope that testing  /* Some options are unpacked into BOOL variables in the hope that testing
 them will be faster than individual option bits. */  them will be faster than individual option bits. */
Line 6644  if (re->top_backref > 0 && re->top_backref >= ocount/3 Line 6669  if (re->top_backref > 0 && re->top_backref >= ocount/3
   DPRINTF(("Got memory to hold back references\n"));    DPRINTF(("Got memory to hold back references\n"));
   }    }
 else md->offset_vector = offsets;  else md->offset_vector = offsets;
   
 md->offset_end = ocount;  md->offset_end = ocount;
 md->offset_max = (2*ocount)/3;  md->offset_max = (2*ocount)/3;
md->offset_overflow = FALSE;md->capture_last = 0;
md->capture_last = -1; 
   
 /* Reset the working variable associated with each extraction. These should  /* 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  never be used unless previously set, but they get saved and restored, and so we
Line 6756  for(;;) Line 6779  for(;;)
   
     if (has_first_char)      if (has_first_char)
       {        {
         pcre_uchar smc;
   
       if (first_char != first_char2)        if (first_char != first_char2)
         while (start_match < end_subject &&          while (start_match < end_subject &&
            *start_match != first_char && *start_match != first_char2)          (smc = RAWUCHARTEST(start_match)) != first_char && smc != first_char2)
           start_match++;            start_match++;
       else        else
        while (start_match < end_subject && *start_match != first_char)        while (start_match < end_subject && RAWUCHARTEST(start_match) != first_char)
           start_match++;            start_match++;
       }        }
   
Line 6793  for(;;) Line 6818  for(;;)
         if (start_match[-1] == CHAR_CR &&          if (start_match[-1] == CHAR_CR &&
              (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&               (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
              start_match < end_subject &&               start_match < end_subject &&
             *start_match == CHAR_NL)             RAWUCHARTEST(start_match) == CHAR_NL)
           start_match++;            start_match++;
         }          }
       }        }
Line 6804  for(;;) Line 6829  for(;;)
       {        {
       while (start_match < end_subject)        while (start_match < end_subject)
         {          {
        register unsigned int c = *start_match;        register pcre_uint32 c = RAWUCHARTEST(start_match);
 #ifndef COMPILE_PCRE8  #ifndef COMPILE_PCRE8
         if (c > 255) c = 255;          if (c > 255) c = 255;
 #endif  #endif
Line 6872  for(;;) Line 6897  for(;;)
           {            {
           while (p < end_subject)            while (p < end_subject)
             {              {
            register int pp = *p++;            register pcre_uint32 pp = RAWUCHARINCTEST(p);
             if (pp == req_char || pp == req_char2) { p--; break; }              if (pp == req_char || pp == req_char2) { p--; break; }
             }              }
           }            }
Line 6880  for(;;) Line 6905  for(;;)
           {            {
           while (p < end_subject)            while (p < end_subject)
             {              {
            if (*p++ == req_char) { p--; break; }            if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
             }              }
           }            }
   
Line 6916  for(;;) Line 6941  for(;;)
   md->match_call_count = 0;    md->match_call_count = 0;
   md->match_function_type = 0;    md->match_function_type = 0;
   md->end_offset_top = 0;    md->end_offset_top = 0;
     md->skip_arg_count = 0;
   rc = match(start_match, md->start_code, start_match, 2, md, NULL, 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;  if (md->hitend && start_partial == NULL)
     {
     start_partial = md->start_used_ptr;
     match_partial = start_match;
     }
   
   switch(rc)    switch(rc)
     {      {
Line 6930  for(;;) Line 6960  for(;;)
   
     case MATCH_SKIP_ARG:      case MATCH_SKIP_ARG:
     new_start_match = start_match;      new_start_match = start_match;
    md->ignore_skip_arg = TRUE;    md->ignore_skip_arg = md->skip_arg_count;
     break;      break;
   
    /* SKIP passes back the next starting point explicitly, but if it is the    /* SKIP passes back the next starting point explicitly, but if it is no
    same as the match we have just done, treat it as NOMATCH. */    greater than the match we have just done, treat it as NOMATCH. */
   
     case MATCH_SKIP:      case MATCH_SKIP:
    if (md->start_match_ptr != start_match)    if (md->start_match_ptr > start_match)
       {        {
       new_start_match = md->start_match_ptr;        new_start_match = md->start_match_ptr;
       break;        break;
Line 6945  for(;;) Line 6975  for(;;)
     /* Fall through */      /* Fall through */
   
     /* NOMATCH and PRUNE advance by one character. THEN at this level acts      /* NOMATCH and PRUNE advance by one character. THEN at this level acts
    exactly like PRUNE. Unset the ignore SKIP-with-argument flag. */    exactly like PRUNE. Unset ignore SKIP-with-argument. */
   
     case MATCH_NOMATCH:      case MATCH_NOMATCH:
     case MATCH_PRUNE:      case MATCH_PRUNE:
     case MATCH_THEN:      case MATCH_THEN:
    md->ignore_skip_arg = FALSE;    md->ignore_skip_arg = 0;
     new_start_match = start_match + 1;      new_start_match = start_match + 1;
 #ifdef SUPPORT_UTF  #ifdef SUPPORT_UTF
     if (utf)      if (utf)
Line 7043  if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) Line 7073  if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
         (arg_offset_max - 2) * sizeof(int));          (arg_offset_max - 2) * sizeof(int));
       DPRINTF(("Copied offsets from temporary memory\n"));        DPRINTF(("Copied offsets from temporary memory\n"));
       }        }
    if (md->end_offset_top > arg_offset_max) md->offset_overflow = TRUE;    if (md->end_offset_top > arg_offset_max) md->capture_last |= OVFLBIT;
     DPRINTF(("Freeing temporary memory\n"));      DPRINTF(("Freeing temporary memory\n"));
     (PUBL(free))(md->offset_vector);      (PUBL(free))(md->offset_vector);
     }      }
Line 7051  if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) Line 7081  if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
   /* Set the return code to the number of captured strings, or 0 if there were    /* Set the return code to the number of captured strings, or 0 if there were
   too many to fit into the vector. */    too many to fit into the vector. */
   
  rc = (md->offset_overflow && md->end_offset_top >= arg_offset_max)?  rc = ((md->capture_last & OVFLBIT) != 0 &&
          md->end_offset_top >= arg_offset_max)?
     0 : md->end_offset_top/2;      0 : md->end_offset_top/2;
   
   /* If there is space in the offset vector, set any unused pairs at the end of    /* If there is space in the offset vector, set any unused pairs at the end of
Line 7116  if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) Line 7147  if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
   
 /* Handle partial matches - disable any mark data */  /* Handle partial matches - disable any mark data */
   
if (start_partial != NULL)if (match_partial != NULL)
   {    {
   DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));    DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
   md->mark = NULL;    md->mark = NULL;
Line 7124  if (start_partial != NULL) Line 7155  if (start_partial != NULL)
     {      {
     offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject);      offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject);
     offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);      offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
       if (offsetcount > 2)
         offsets[2] = (int)(match_partial - (PCRE_PUCHAR)subject);
     }      }
   rc = PCRE_ERROR_PARTIAL;    rc = PCRE_ERROR_PARTIAL;
   }    }

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.5


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>