Diff for /win32/pcre/pcre_exec.c between versions 1.2 and 1.5

version 1.2, 2009/04/10 12:53:37 version 1.5, 2011/02/01 05:03:42
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-2008 University of Cambridge             Copyright (c) 1997-2010 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 71  defined PCRE_ERROR_xxx codes, which are Line 71  defined PCRE_ERROR_xxx codes, which are
 /* Special internal returns from the match() function. Make them sufficiently  /* Special internal returns from the match() function. Make them sufficiently
 negative to avoid the external error codes. */  negative to avoid the external error codes. */
   
 #define MATCH_COMMIT       (-999)  #define MATCH_ACCEPT       (-999)
 #define MATCH_PRUNE        (-998)  #define MATCH_COMMIT       (-998)
 #define MATCH_SKIP         (-997)  #define MATCH_PRUNE        (-997)
 #define MATCH_THEN         (-996)  #define MATCH_SKIP         (-996)
   #define MATCH_SKIP_ARG     (-995)
   #define MATCH_THEN         (-994)
   
   /* This is a convenience macro for code that occurs many times. */
   
   #define MRRETURN(ra) \
     { \
     md->mark = markptr; \
     RRETURN(ra); \
     }
   
 /* Maximum number of ints of offset to save on the stack for recursive calls.  /* 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  static const char rep_max[] = { 0, 0, 0, Line 99  static const char rep_max[] = { 0, 0, 0,
   
   
   
 #ifdef DEBUG  #ifdef PCRE_DEBUG
 /*************************************************  /*************************************************
 *        Debugging function to print chars       *  *        Debugging function to print chars       *
 *************************************************/  *************************************************/
Line 141  match_ref(int offset, register USPTR ept Line 151  match_ref(int offset, register USPTR ept
 {  {
 USPTR p = md->start_subject + md->offset_vector[offset];  USPTR p = md->start_subject + md->offset_vector[offset];
   
 #ifdef DEBUG  #ifdef PCRE_DEBUG
 if (eptr >= md->end_subject)  if (eptr >= md->end_subject)
   printf("matching subject <null>");    printf("matching subject <null>");
 else  else
Line 245  enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM Line 255  enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM
        RM21,  RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,         RM21,  RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
        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 };         RM51,  RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,
          RM61,  RM62 };
   
 /* These versions of the macros use the stack, as normal. There are debugging  /* 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
 actuall used in this definition. */  actually used in this definition. */
   
 #ifndef NO_RECURSE  #ifndef NO_RECURSE
 #define REGISTER register  #define REGISTER register
   
 #ifdef DEBUG  #ifdef PCRE_DEBUG
 #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \  #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
   { \    { \
   printf("match() called in line %d\n", __LINE__); \    printf("match() called in line %d\n", __LINE__); \
   rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1); \    rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,rdepth+1); \
   printf("to line %d\n", __LINE__); \    printf("to line %d\n", __LINE__); \
   }    }
 #define RRETURN(ra) \  #define RRETURN(ra) \
Line 268  actuall used in this definition. */ Line 279  actuall used in this definition. */
   }    }
 #else  #else
 #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \  #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
   rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1)    rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,rdepth+1)
 #define RRETURN(ra) return ra  #define RRETURN(ra) return ra
 #endif  #endif
   
Line 283  argument of match(), which never changes Line 294  argument of match(), which never changes
   
 #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\  #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\
   {\    {\
   heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\    heapframe *newframe = (heapframe *)(pcre_stack_malloc)(sizeof(heapframe));\
     if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
   frame->Xwhere = rw; \    frame->Xwhere = rw; \
   newframe->Xeptr = ra;\    newframe->Xeptr = ra;\
   newframe->Xecode = rb;\    newframe->Xecode = rb;\
   newframe->Xmstart = mstart;\    newframe->Xmstart = mstart;\
     newframe->Xmarkptr = markptr;\
   newframe->Xoffset_top = rc;\    newframe->Xoffset_top = rc;\
   newframe->Xims = re;\    newframe->Xims = re;\
   newframe->Xeptrb = rf;\    newframe->Xeptrb = rf;\
Line 303  argument of match(), which never changes Line 316  argument of match(), which never changes
   
 #define RRETURN(ra)\  #define RRETURN(ra)\
   {\    {\
   heapframe *newframe = frame;\    heapframe *oldframe = frame;\
   frame = newframe->Xprevframe;\    frame = oldframe->Xprevframe;\
   (pcre_stack_free)(newframe);\    (pcre_stack_free)(oldframe);\
   if (frame != NULL)\    if (frame != NULL)\
     {\      {\
     rrc = ra;\      rrc = ra;\
Line 322  typedef struct heapframe { Line 335  typedef struct heapframe {
   
   /* Function arguments that may change */    /* Function arguments that may change */
   
   const uschar *Xeptr;    USPTR Xeptr;
   const uschar *Xecode;    const uschar *Xecode;
   const uschar *Xmstart;    USPTR Xmstart;
     USPTR Xmarkptr;
   int Xoffset_top;    int Xoffset_top;
   long int Xims;    long int Xims;
   eptrblock *Xeptrb;    eptrblock *Xeptrb;
Line 333  typedef struct heapframe { Line 347  typedef struct heapframe {
   
   /* Function local variables */    /* Function local variables */
   
   const uschar *Xcallpat;    USPTR Xcallpat;
   const uschar *Xcharptr;  #ifdef SUPPORT_UTF8
   const uschar *Xdata;    USPTR Xcharptr;
   const uschar *Xnext;  #endif
   const uschar *Xpp;    USPTR Xdata;
   const uschar *Xprev;    USPTR Xnext;
   const uschar *Xsaved_eptr;    USPTR Xpp;
     USPTR Xprev;
     USPTR Xsaved_eptr;
   
   recursion_info Xnew_recursive;    recursion_info Xnew_recursive;
   
Line 360  typedef struct heapframe { Line 376  typedef struct heapframe {
   uschar Xocchars[8];    uschar Xocchars[8];
 #endif  #endif
   
     int Xcodelink;
   int Xctype;    int Xctype;
   unsigned int Xfc;    unsigned int Xfc;
   int Xfi;    int Xfi;
Line 395  typedef struct heapframe { Line 412  typedef struct heapframe {
   
 /* This function is called recursively in many circumstances. Whenever it  /* This function is called recursively in many circumstances. Whenever it
 returns a negative (error) response, the outer incarnation must also return the  returns a negative (error) response, the outer incarnation must also return the
 same response.  same response. */
   
 Performance note: It might be tempting to extract commonly used fields from the  /* These macros pack up tests that are used for partial matching, and which
 md structure (e.g. utf8, end_subject) into individual variables to improve  appears several times in the code. We set the "hit end" flag if the pointer is
   at the end of the subject and also past the start of the subject (i.e.
   something has been matched). For hard partial matching, we then return
   immediately. The second one is used when we already know we are past the end of
   the subject. */
   
   #define CHECK_PARTIAL()\
     if (md->partial != 0 && eptr >= md->end_subject && \
         eptr > md->start_used_ptr) \
       { \
       md->hitend = TRUE; \
       if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL); \
       }
   
   #define SCHECK_PARTIAL()\
     if (md->partial != 0 && eptr > md->start_used_ptr) \
       { \
       md->hitend = TRUE; \
       if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL); \
       }
   
   
   /* Performance note: It might be tempting to extract commonly used fields from
   the md structure (e.g. utf8, end_subject) into individual variables to improve
 performance. Tests using gcc on a SPARC disproved this; in the first case, it  performance. Tests using gcc on a SPARC disproved this; in the first case, it
 made performance worse.  made performance worse.
   
Line 407  Arguments: Line 447  Arguments:
    ecode       pointer to current position in compiled code     ecode       pointer to current position in compiled code
    mstart      pointer to the current match start position (can be modified     mstart      pointer to the current match start position (can be modified
                  by encountering \K)                   by encountering \K)
      markptr     pointer to the most recent MARK name, or NULL
    offset_top  current top pointer     offset_top  current top pointer
    md          pointer to "static" info for the match     md          pointer to "static" info for the match
    ims         current /i, /m, and /s options     ims         current /i, /m, and /s options
Line 420  Arguments: Line 461  Arguments:
   
 Returns:       MATCH_MATCH if matched            )  these values are >= 0  Returns:       MATCH_MATCH if matched            )  these values are >= 0
                MATCH_NOMATCH if failed to match  )                 MATCH_NOMATCH if failed to match  )
                  a negative MATCH_xxx value for PRUNE, SKIP, etc
                a negative PCRE_ERROR_xxx value if aborted by an error condition                 a negative PCRE_ERROR_xxx value if aborted by an error condition
                  (e.g. stopped by repeated call or recursion limit)                   (e.g. stopped by repeated call or recursion limit)
 */  */
   
 static int  static int
 match(REGISTER USPTR eptr, REGISTER const uschar *ecode, const uschar *mstart,  match(REGISTER USPTR eptr, REGISTER const uschar *ecode, USPTR mstart,
   int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,    const uschar *markptr, int offset_top, match_data *md, unsigned long int ims,
   int flags, unsigned int rdepth)    eptrblock *eptrb, int flags, unsigned int rdepth)
 {  {
 /* These variables do not need to be preserved over recursion in this function,  /* These variables do not need to be preserved over recursion in this function,
 so they can be ordinary variables in all cases. Mark some of them with  so they can be ordinary variables in all cases. Mark some of them with
Line 439  register unsigned int c;   /* Character Line 481  register unsigned int c;   /* Character
 register BOOL utf8;        /* Local copy of UTF-8 flag for speed */  register BOOL utf8;        /* Local copy of UTF-8 flag for speed */
   
 BOOL minimize, possessive; /* Quantifier options */  BOOL minimize, possessive; /* Quantifier options */
   int condcode;
   
 /* When recursion is not being used, all "local" variables that have to be  /* When recursion is not being used, all "local" variables that have to be
 preserved over calls to RMATCH() are part of a "frame" which is obtained from  preserved over calls to RMATCH() are part of a "frame" which is obtained from
Line 446  heap storage. Set up the top-level frame Line 489  heap storage. Set up the top-level frame
 heap whenever RMATCH() does a "recursion". See the macro definitions above. */  heap whenever RMATCH() does a "recursion". See the macro definitions above. */
   
 #ifdef NO_RECURSE  #ifdef NO_RECURSE
 heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe));  heapframe *frame = (heapframe *)(pcre_stack_malloc)(sizeof(heapframe));
   if (frame == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
 frame->Xprevframe = NULL;            /* Marks the top level */  frame->Xprevframe = NULL;            /* Marks the top level */
   
 /* Copy in the original argument variables */  /* Copy in the original argument variables */
Line 454  frame->Xprevframe = NULL;            /* Line 498  frame->Xprevframe = NULL;            /*
 frame->Xeptr = eptr;  frame->Xeptr = eptr;
 frame->Xecode = ecode;  frame->Xecode = ecode;
 frame->Xmstart = mstart;  frame->Xmstart = mstart;
   frame->Xmarkptr = markptr;
 frame->Xoffset_top = offset_top;  frame->Xoffset_top = offset_top;
 frame->Xims = ims;  frame->Xims = ims;
 frame->Xeptrb = eptrb;  frame->Xeptrb = eptrb;
Line 469  HEAP_RECURSE: Line 514  HEAP_RECURSE:
 #define eptr               frame->Xeptr  #define eptr               frame->Xeptr
 #define ecode              frame->Xecode  #define ecode              frame->Xecode
 #define mstart             frame->Xmstart  #define mstart             frame->Xmstart
   #define markptr            frame->Xmarkptr
 #define offset_top         frame->Xoffset_top  #define offset_top         frame->Xoffset_top
 #define ims                frame->Xims  #define ims                frame->Xims
 #define eptrb              frame->Xeptrb  #define eptrb              frame->Xeptrb
Line 481  HEAP_RECURSE: Line 527  HEAP_RECURSE:
 #define charptr            frame->Xcharptr  #define charptr            frame->Xcharptr
 #endif  #endif
 #define callpat            frame->Xcallpat  #define callpat            frame->Xcallpat
   #define codelink           frame->Xcodelink
 #define data               frame->Xdata  #define data               frame->Xdata
 #define next               frame->Xnext  #define next               frame->Xnext
 #define pp                 frame->Xpp  #define pp                 frame->Xpp
Line 561  int oclength; Line 608  int oclength;
 uschar occhars[8];  uschar occhars[8];
 #endif  #endif
   
   int codelink;
 int ctype;  int ctype;
 int length;  int length;
 int max;  int max;
Line 594  TAIL_RECURSE: Line 642  TAIL_RECURSE:
 /* OK, now we can get on with the real code of the function. Recursive calls  /* OK, now we can get on with the real code of the function. Recursive calls
 are specified by the macro RMATCH and RRETURN is used to return. When  are specified by the macro RMATCH and RRETURN is used to return. When
 NO_RECURSE is *not* defined, these just turn into a recursive call to match()  NO_RECURSE is *not* defined, these just turn into a recursive call to match()
 and a "return", respectively (possibly with some debugging if DEBUG is  and a "return", respectively (possibly with some debugging if PCRE_DEBUG is
 defined). However, RMATCH isn't like a function call because it's quite a  defined). However, RMATCH isn't like a function call because it's quite a
 complicated macro. It has to be used in one particular way. This shouldn't,  complicated macro. It has to be used in one particular way. This shouldn't,
 however, impact performance when true recursion is being used. */  however, impact performance when true recursion is being used. */
Line 636  for (;;) Line 684  for (;;)
   minimize = possessive = FALSE;    minimize = possessive = FALSE;
   op = *ecode;    op = *ecode;
   
   /* For partial matching, remember if we ever hit the end of the subject after  
   matching at least one subject character. */  
   
   if (md->partial &&  
       eptr >= md->end_subject &&  
       eptr > mstart)  
     md->hitend = TRUE;  
   
   switch(op)    switch(op)
     {      {
       case OP_MARK:
       markptr = ecode + 2;
       RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
         ims, eptrb, flags, RM55);
   
       /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an
       argument, and we must check whether that argument matches this MARK's
       argument. It is passed back in md->start_match_ptr (an overloading of that
       variable). If it does match, we reset that variable to the current subject
       position and return MATCH_SKIP. Otherwise, pass back the return code
       unaltered. */
   
       if (rrc == MATCH_SKIP_ARG &&
           strcmp((char *)markptr, (char *)(md->start_match_ptr)) == 0)
         {
         md->start_match_ptr = eptr;
         RRETURN(MATCH_SKIP);
         }
   
       if (md->mark == NULL) md->mark = markptr;
       RRETURN(rrc);
   
     case OP_FAIL:      case OP_FAIL:
     RRETURN(MATCH_NOMATCH);      MRRETURN(MATCH_NOMATCH);
   
       /* COMMIT overrides PRUNE, SKIP, and THEN */
   
       case OP_COMMIT:
       RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
         ims, eptrb, flags, RM52);
       if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&
           rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG &&
           rrc != MATCH_THEN)
         RRETURN(rrc);
       MRRETURN(MATCH_COMMIT);
   
       /* PRUNE overrides THEN */
   
     case OP_PRUNE:      case OP_PRUNE:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,      RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
       ims, eptrb, flags, RM51);        ims, eptrb, flags, RM51);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
       MRRETURN(MATCH_PRUNE);
   
       case OP_PRUNE_ARG:
       RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
         ims, eptrb, flags, RM56);
       if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
       md->mark = ecode + 2;
     RRETURN(MATCH_PRUNE);      RRETURN(MATCH_PRUNE);
   
     case OP_COMMIT:      /* SKIP overrides PRUNE and THEN */
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,  
       ims, eptrb, flags, RM52);  
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);  
     RRETURN(MATCH_COMMIT);  
   
     case OP_SKIP:      case OP_SKIP:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,      RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
       ims, eptrb, flags, RM53);        ims, eptrb, flags, RM53);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);      if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
         RRETURN(rrc);
     md->start_match_ptr = eptr;   /* Pass back current position */      md->start_match_ptr = eptr;   /* Pass back current position */
     RRETURN(MATCH_SKIP);      MRRETURN(MATCH_SKIP);
   
       case OP_SKIP_ARG:
       RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
         ims, eptrb, flags, RM57);
       if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
         RRETURN(rrc);
   
       /* Pass back the current skip name by overloading md->start_match_ptr and
       returning the special MATCH_SKIP_ARG return code. This will either be
       caught by a matching MARK, or get to the top, where it is treated the same
       as PRUNE. */
   
       md->start_match_ptr = ecode + 2;
       RRETURN(MATCH_SKIP_ARG);
   
       /* For THEN (and THEN_ARG) we pass back the address of the bracket or
       the alt that is at the start of the current branch. This makes it possible
       to skip back past alternatives that precede the THEN within the current
       branch. */
   
     case OP_THEN:      case OP_THEN:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,      RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
       ims, eptrb, flags, RM54);        ims, eptrb, flags, RM54);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       md->start_match_ptr = ecode - GET(ecode, 1);
       MRRETURN(MATCH_THEN);
   
       case OP_THEN_ARG:
       RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1+LINK_SIZE],
         offset_top, md, ims, eptrb, flags, RM58);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       md->start_match_ptr = ecode - GET(ecode, 1);
       md->mark = ecode + LINK_SIZE + 2;
     RRETURN(MATCH_THEN);      RRETURN(MATCH_THEN);
   
     /* Handle a capturing bracket. If there is space in the offset vector, save      /* Handle a capturing bracket. If there is space in the offset vector, save
Line 693  for (;;) Line 800  for (;;)
     number = GET2(ecode, 1+LINK_SIZE);      number = GET2(ecode, 1+LINK_SIZE);
     offset = number << 1;      offset = number << 1;
   
 #ifdef DEBUG  #ifdef PCRE_DEBUG
     printf("start bracket %d\n", number);      printf("start bracket %d\n", number);
     printf("subject=");      printf("subject=");
     pchars(eptr, 16, TRUE, md);      pchars(eptr, 16, TRUE, md);
Line 708  for (;;) Line 815  for (;;)
       save_capture_last = md->capture_last;        save_capture_last = md->capture_last;
   
       DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));        DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
       md->offset_vector[md->offset_end - number] = eptr - md->start_subject;        md->offset_vector[md->offset_end - number] =
           (int)(eptr - md->start_subject);
   
       flags = (op == OP_SCBRA)? match_cbegroup : 0;        flags = (op == OP_SCBRA)? match_cbegroup : 0;
       do        do
         {          {
         RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,          RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
           ims, eptrb, flags, RM1);            ims, eptrb, flags, RM1);
         if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);          if (rrc != MATCH_NOMATCH &&
               (rrc != MATCH_THEN || md->start_match_ptr != ecode))
             RRETURN(rrc);
         md->capture_last = save_capture_last;          md->capture_last = save_capture_last;
         ecode += GET(ecode, 1);          ecode += GET(ecode, 1);
         }          }
Line 727  for (;;) Line 837  for (;;)
       md->offset_vector[offset+1] = save_offset2;        md->offset_vector[offset+1] = save_offset2;
       md->offset_vector[md->offset_end - number] = save_offset3;        md->offset_vector[md->offset_end - number] = save_offset3;
   
         if (rrc != MATCH_THEN) md->mark = markptr;
       RRETURN(MATCH_NOMATCH);        RRETURN(MATCH_NOMATCH);
       }        }
   
Line 766  for (;;) Line 877  for (;;)
   
         RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,          RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
           eptrb, flags, RM48);            eptrb, flags, RM48);
           if (rrc == MATCH_NOMATCH) md->mark = markptr;
         RRETURN(rrc);          RRETURN(rrc);
         }          }
   
Line 774  for (;;) Line 886  for (;;)
   
       RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,        RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
         eptrb, flags, RM2);          eptrb, flags, RM2);
       if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);        if (rrc != MATCH_NOMATCH &&
             (rrc != MATCH_THEN || md->start_match_ptr != ecode))
           RRETURN(rrc);
       ecode += GET(ecode, 1);        ecode += GET(ecode, 1);
       }        }
     /* Control never reaches here. */      /* Control never reaches here. */
Line 787  for (;;) Line 901  for (;;)
   
     case OP_COND:      case OP_COND:
     case OP_SCOND:      case OP_SCOND:
     if (ecode[LINK_SIZE+1] == OP_RREF)         /* Recursion test */      codelink= GET(ecode, 1);
   
       /* Because of the way auto-callout works during compile, a callout item is
       inserted between OP_COND and an assertion condition. */
   
       if (ecode[LINK_SIZE+1] == OP_CALLOUT)
       {        {
       offset = GET2(ecode, LINK_SIZE + 2);     /* Recursion group number*/        if (pcre_callout != NULL)
       condition = md->recursive != NULL &&          {
         (offset == RREF_ANY || offset == md->recursive->group_num);          pcre_callout_block cb;
       ecode += condition? 3 : GET(ecode, 1);          cb.version          = 1;   /* Version 1 of the callout block */
           cb.callout_number   = ecode[LINK_SIZE+2];
           cb.offset_vector    = md->offset_vector;
           cb.subject          = (PCRE_SPTR)md->start_subject;
           cb.subject_length   = (int)(md->end_subject - md->start_subject);
           cb.start_match      = (int)(mstart - md->start_subject);
           cb.current_position = (int)(eptr - md->start_subject);
           cb.pattern_position = GET(ecode, LINK_SIZE + 3);
           cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE);
           cb.capture_top      = offset_top/2;
           cb.capture_last     = md->capture_last;
           cb.callout_data     = md->callout_data;
           if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH);
           if (rrc < 0) RRETURN(rrc);
           }
         ecode += _pcre_OP_lengths[OP_CALLOUT];
         }
   
       condcode = ecode[LINK_SIZE+1];
   
       /* Now see what the actual condition is */
   
       if (condcode == OP_RREF || condcode == OP_NRREF)    /* Recursion test */
         {
         if (md->recursive == NULL)                /* Not recursing => FALSE */
           {
           condition = FALSE;
           ecode += GET(ecode, 1);
           }
         else
           {
           int recno = GET2(ecode, LINK_SIZE + 2);   /* Recursion group number*/
           condition =  (recno == RREF_ANY || recno == md->recursive->group_num);
   
           /* If the test is for recursion into a specific subpattern, and it is
           false, but the test was set up by name, scan the table to see if the
           name refers to any other numbers, and test them. The condition is true
           if any one is set. */
   
           if (!condition && condcode == OP_NRREF && recno != RREF_ANY)
             {
             uschar *slotA = md->name_table;
             for (i = 0; i < md->name_count; i++)
               {
               if (GET2(slotA, 0) == recno) break;
               slotA += md->name_entry_size;
               }
   
             /* Found a name for the number - there can be only one; duplicate
             names for different numbers are allowed, but not vice versa. First
             scan down for duplicates. */
   
             if (i < md->name_count)
               {
               uschar *slotB = slotA;
               while (slotB > md->name_table)
                 {
                 slotB -= md->name_entry_size;
                 if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 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((char *)slotA + 2, (char *)slotB + 2) == 0)
                     {
                     condition = GET2(slotB, 0) == md->recursive->group_num;
                     if (condition) break;
                     }
                   else break;
                   }
                 }
               }
             }
   
           /* Chose branch according to the condition */
   
           ecode += condition? 3 : GET(ecode, 1);
           }
       }        }
   
     else if (ecode[LINK_SIZE+1] == OP_CREF)    /* Group used test */      else if (condcode == OP_CREF || condcode == OP_NCREF)  /* Group used test */
       {        {
       offset = GET2(ecode, LINK_SIZE+2) << 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;
   
         /* If the numbered capture is unset, but the reference was by name,
         scan the table to see if the name refers to any other numbers, and test
         them. The condition is true if any one is set. This is tediously similar
         to the code above, but not close enough to try to amalgamate. */
   
         if (!condition && condcode == OP_NCREF)
           {
           int refno = offset >> 1;
           uschar *slotA = md->name_table;
   
           for (i = 0; i < md->name_count; i++)
             {
             if (GET2(slotA, 0) == refno) break;
             slotA += md->name_entry_size;
             }
   
           /* Found a name for the number - there can be only one; duplicate names
           for different numbers are allowed, but not vice versa. First scan down
           for duplicates. */
   
           if (i < md->name_count)
             {
             uschar *slotB = slotA;
             while (slotB > md->name_table)
               {
               slotB -= md->name_entry_size;
               if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 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((char *)slotA + 2, (char *)slotB + 2) == 0)
                   {
                   offset = GET2(slotB, 0) << 1;
                   condition = offset < offset_top &&
                     md->offset_vector[offset] >= 0;
                   if (condition) break;
                   }
                 else break;
                 }
               }
             }
           }
   
         /* Chose branch according to the condition */
   
       ecode += condition? 3 : GET(ecode, 1);        ecode += condition? 3 : GET(ecode, 1);
       }        }
   
     else if (ecode[LINK_SIZE+1] == OP_DEF)     /* DEFINE - always false */      else if (condcode == OP_DEF)     /* DEFINE - always false */
       {        {
       condition = FALSE;        condition = FALSE;
       ecode += GET(ecode, 1);        ecode += GET(ecode, 1);
Line 822  for (;;) Line 1089  for (;;)
         ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2);          ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2);
         while (*ecode == OP_ALT) ecode += GET(ecode, 1);          while (*ecode == OP_ALT) ecode += GET(ecode, 1);
         }          }
       else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)        else if (rrc != MATCH_NOMATCH &&
                 (rrc != MATCH_THEN || md->start_match_ptr != ecode))
         {          {
         RRETURN(rrc);         /* Need braces because of following else */          RRETURN(rrc);         /* Need braces because of following else */
         }          }
       else        else
         {          {
         condition = FALSE;          condition = FALSE;
         ecode += GET(ecode, 1);          ecode += codelink;
         }          }
       }        }
   
Line 852  for (;;) Line 1120  for (;;)
         goto TAIL_RECURSE;          goto TAIL_RECURSE;
         }          }
       }        }
     else                         /* Condition false & no 2nd alternative */      else                         /* Condition false & no alternative */
       {        {
       ecode += 1 + LINK_SIZE;        ecode += 1 + LINK_SIZE;
       }        }
     break;      break;
   
   
       /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes,
       to close any currently open capturing brackets. */
   
       case OP_CLOSE:
       number = GET2(ecode, 1);
       offset = number << 1;
   
   #ifdef PCRE_DEBUG
         printf("end bracket %d at *ACCEPT", number);
         printf("\n");
   #endif
   
       md->capture_last = number;
       if (offset >= md->offset_max) md->offset_overflow = TRUE; else
         {
         md->offset_vector[offset] =
           md->offset_vector[md->offset_end - number];
         md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
         if (offset_top <= offset) offset_top = offset + 2;
         }
       ecode += 3;
       break;
   
   
     /* End of the pattern, either real or forced. If we are in a top-level      /* End of the pattern, either real or forced. If we are in a top-level
     recursion, we should restore the offsets appropriately and continue from      recursion, we should restore the offsets appropriately and continue from
     after the call. */      after the call. */
Line 872  for (;;) Line 1164  for (;;)
       md->recursive = rec->prevrec;        md->recursive = rec->prevrec;
       memmove(md->offset_vector, rec->offset_save,        memmove(md->offset_vector, rec->offset_save,
         rec->saved_max * sizeof(int));          rec->saved_max * sizeof(int));
       mstart = rec->save_start;        offset_top = rec->save_offset_top;
       ims = original_ims;        ims = original_ims;
       ecode = rec->after_call;        ecode = rec->after_call;
       break;        break;
       }        }
   
     /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty      /* Otherwise, if we have matched an empty string, fail if PCRE_NOTEMPTY is
     string - backtracking will then try other alternatives, if any. */      set, or if PCRE_NOTEMPTY_ATSTART is set and we have matched at the start of
       the subject. In both cases, backtracking will then try other alternatives,
       if any. */
   
       if (eptr == mstart &&
           (md->notempty ||
             (md->notempty_atstart &&
               mstart == md->start_subject + md->start_offset)))
         MRRETURN(MATCH_NOMATCH);
   
       /* Otherwise, we have a match. */
   
     if (md->notempty && eptr == mstart) RRETURN(MATCH_NOMATCH);  
     md->end_match_ptr = eptr;           /* Record where we ended */      md->end_match_ptr = eptr;           /* Record where we ended */
     md->end_offset_top = offset_top;    /* and how many extracts were taken */      md->end_offset_top = offset_top;    /* and how many extracts were taken */
     md->start_match_ptr = mstart;       /* and the start (\K can modify) */      md->start_match_ptr = mstart;       /* and the start (\K can modify) */
     RRETURN(MATCH_MATCH);  
       /* For some reason, the macros don't work properly if an expression is
       given as the argument to MRRETURN when the heap is in use. */
   
       rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT;
       MRRETURN(rrc);
   
     /* Change option settings */      /* Change option settings */
   
Line 907  for (;;) Line 1213  for (;;)
       {        {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
         RM4);          RM4);
       if (rrc == MATCH_MATCH) break;        if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
       if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);          {
           mstart = md->start_match_ptr;   /* In case \K reset it */
           break;
           }
         if (rrc != MATCH_NOMATCH &&
             (rrc != MATCH_THEN || md->start_match_ptr != ecode))
           RRETURN(rrc);
       ecode += GET(ecode, 1);        ecode += GET(ecode, 1);
       }        }
     while (*ecode == OP_ALT);      while (*ecode == OP_ALT);
     if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);      if (*ecode == OP_KET) MRRETURN(MATCH_NOMATCH);
   
     /* If checking an assertion for a condition, return MATCH_MATCH. */      /* If checking an assertion for a condition, return MATCH_MATCH. */
   
Line 926  for (;;) Line 1238  for (;;)
     offset_top = md->end_offset_top;      offset_top = md->end_offset_top;
     continue;      continue;
   
     /* Negative assertion: all branches must fail to match */      /* Negative assertion: all branches must fail to match. Encountering SKIP,
       PRUNE, or COMMIT means we must assume failure without checking subsequent
       branches. */
   
     case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
     case OP_ASSERTBACK_NOT:      case OP_ASSERTBACK_NOT:
Line 934  for (;;) Line 1248  for (;;)
       {        {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
         RM5);          RM5);
       if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH);        if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) MRRETURN(MATCH_NOMATCH);
       if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);        if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT)
           {
           do ecode += GET(ecode,1); while (*ecode == OP_ALT);
           break;
           }
         if (rrc != MATCH_NOMATCH &&
             (rrc != MATCH_THEN || md->start_match_ptr != ecode))
           RRETURN(rrc);
       ecode += GET(ecode,1);        ecode += GET(ecode,1);
       }        }
     while (*ecode == OP_ALT);      while (*ecode == OP_ALT);
Line 958  for (;;) Line 1279  for (;;)
       while (i-- > 0)        while (i-- > 0)
         {          {
         eptr--;          eptr--;
         if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);          if (eptr < md->start_subject) MRRETURN(MATCH_NOMATCH);
         BACKCHAR(eptr);          BACKCHAR(eptr);
         }          }
       }        }
Line 969  for (;;) Line 1290  for (;;)
   
       {        {
       eptr -= GET(ecode, 1);        eptr -= GET(ecode, 1);
       if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);        if (eptr < md->start_subject) MRRETURN(MATCH_NOMATCH);
       }        }
   
     /* Skip to next op code */      /* Save the earliest consulted character, then skip to next op code */
   
       if (eptr < md->start_used_ptr) md->start_used_ptr = eptr;
     ecode += 1 + LINK_SIZE;      ecode += 1 + LINK_SIZE;
     break;      break;
   
Line 989  for (;;) Line 1311  for (;;)
       cb.callout_number   = ecode[1];        cb.callout_number   = ecode[1];
       cb.offset_vector    = md->offset_vector;        cb.offset_vector    = md->offset_vector;
       cb.subject          = (PCRE_SPTR)md->start_subject;        cb.subject          = (PCRE_SPTR)md->start_subject;
       cb.subject_length   = md->end_subject - md->start_subject;        cb.subject_length   = (int)(md->end_subject - md->start_subject);
       cb.start_match      = mstart - md->start_subject;        cb.start_match      = (int)(mstart - md->start_subject);
       cb.current_position = eptr - md->start_subject;        cb.current_position = (int)(eptr - md->start_subject);
       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;
       cb.callout_data     = md->callout_data;        cb.callout_data     = md->callout_data;
       if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH);        if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH);
       if (rrc < 0) RRETURN(rrc);        if (rrc < 0) RRETURN(rrc);
       }        }
     ecode += 2 + 2*LINK_SIZE;      ecode += 2 + 2*LINK_SIZE;
Line 1052  for (;;) Line 1374  for (;;)
   
       memcpy(new_recursive.offset_save, md->offset_vector,        memcpy(new_recursive.offset_save, md->offset_vector,
             new_recursive.saved_max * sizeof(int));              new_recursive.saved_max * sizeof(int));
       new_recursive.save_start = mstart;        new_recursive.save_offset_top = offset_top;
       mstart = eptr;  
   
       /* OK, now we can do the recursion. For each top-level alternative we        /* OK, now we can do the recursion. For each top-level alternative we
       restore the offset and recursion data. */        restore the offset and recursion data. */
Line 1064  for (;;) Line 1385  for (;;)
         {          {
         RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,          RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,
           md, ims, eptrb, flags, RM6);            md, ims, eptrb, flags, RM6);
         if (rrc == MATCH_MATCH)          if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
           {            {
           DPRINTF(("Recursion matched\n"));            DPRINTF(("Recursion matched\n"));
           md->recursive = new_recursive.prevrec;            md->recursive = new_recursive.prevrec;
           if (new_recursive.offset_save != stacksave)            if (new_recursive.offset_save != stacksave)
             (pcre_free)(new_recursive.offset_save);              (pcre_free)(new_recursive.offset_save);
           RRETURN(MATCH_MATCH);            MRRETURN(MATCH_MATCH);
           }            }
         else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)          else if (rrc != MATCH_NOMATCH &&
                   (rrc != MATCH_THEN || md->start_match_ptr != ecode))
           {            {
           DPRINTF(("Recursion gave error %d\n", rrc));            DPRINTF(("Recursion gave error %d\n", rrc));
             if (new_recursive.offset_save != stacksave)
               (pcre_free)(new_recursive.offset_save);
           RRETURN(rrc);            RRETURN(rrc);
           }            }
   
Line 1089  for (;;) Line 1413  for (;;)
       md->recursive = new_recursive.prevrec;        md->recursive = new_recursive.prevrec;
       if (new_recursive.offset_save != stacksave)        if (new_recursive.offset_save != stacksave)
         (pcre_free)(new_recursive.offset_save);          (pcre_free)(new_recursive.offset_save);
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
       }        }
     /* Control never reaches here */      /* Control never reaches here */
   
Line 1098  for (;;) Line 1422  for (;;)
     a move back into the brackets. Friedl calls these "atomic" subpatterns.      a move back into the brackets. Friedl calls these "atomic" subpatterns.
     Check the alternative branches in turn - the matching won't pass the KET      Check the alternative branches in turn - the matching won't pass the KET
     for this kind of subpattern. If any one branch matches, we carry on as at      for this kind of subpattern. If any one branch matches, we carry on as at
     the end of a normal bracket, leaving the subject pointer. */      the end of a normal bracket, leaving the subject pointer, but resetting
       the start-of-match value in case it was changed by \K. */
   
     case OP_ONCE:      case OP_ONCE:
     prev = ecode;      prev = ecode;
Line 1107  for (;;) Line 1432  for (;;)
     do      do
       {        {
       RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7);        RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7);
       if (rrc == MATCH_MATCH) break;        if (rrc == MATCH_MATCH)  /* Note: _not_ MATCH_ACCEPT */
       if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);          {
           mstart = md->start_match_ptr;
           break;
           }
         if (rrc != MATCH_NOMATCH &&
             (rrc != MATCH_THEN || md->start_match_ptr != ecode))
           RRETURN(rrc);
       ecode += GET(ecode,1);        ecode += GET(ecode,1);
       }        }
     while (*ecode == OP_ALT);      while (*ecode == OP_ALT);
Line 1226  for (;;) Line 1557  for (;;)
       }        }
     else saved_eptr = NULL;      else saved_eptr = NULL;
   
     /* If we are at the end of an assertion group, stop matching and return      /* If we are at the end of an assertion group or an atomic group, stop
     MATCH_MATCH, but record the current high water mark for use by positive      matching and return MATCH_MATCH, but record the current high water mark for
     assertions. Do this also for the "once" (atomic) groups. */      use by positive assertions. We also need to record the match start in case
       it was changed by \K. */
   
     if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||      if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
         *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||          *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
Line 1236  for (;;) Line 1568  for (;;)
       {        {
       md->end_match_ptr = eptr;      /* For ONCE */        md->end_match_ptr = eptr;      /* For ONCE */
       md->end_offset_top = offset_top;        md->end_offset_top = offset_top;
       RRETURN(MATCH_MATCH);        md->start_match_ptr = mstart;
         MRRETURN(MATCH_MATCH);
       }        }
   
     /* For capturing groups we have to check the group number back at the start      /* For capturing groups we have to check the group number back at the start
Line 1250  for (;;) Line 1583  for (;;)
       number = GET2(prev, 1+LINK_SIZE);        number = GET2(prev, 1+LINK_SIZE);
       offset = number << 1;        offset = number << 1;
   
 #ifdef DEBUG  #ifdef PCRE_DEBUG
       printf("end bracket %d", number);        printf("end bracket %d", number);
       printf("\n");        printf("\n");
 #endif  #endif
Line 1260  for (;;) Line 1593  for (;;)
         {          {
         md->offset_vector[offset] =          md->offset_vector[offset] =
           md->offset_vector[md->offset_end - number];            md->offset_vector[md->offset_end - number];
         md->offset_vector[offset+1] = eptr - md->start_subject;          md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
         if (offset_top <= offset) offset_top = offset + 2;          if (offset_top <= offset) offset_top = offset + 2;
         }          }
   
Line 1272  for (;;) Line 1605  for (;;)
         recursion_info *rec = md->recursive;          recursion_info *rec = md->recursive;
         DPRINTF(("Recursion (%d) succeeded - continuing\n", number));          DPRINTF(("Recursion (%d) succeeded - continuing\n", number));
         md->recursive = rec->prevrec;          md->recursive = rec->prevrec;
         mstart = rec->save_start;  
         memcpy(md->offset_vector, rec->offset_save,          memcpy(md->offset_vector, rec->offset_save,
           rec->saved_max * sizeof(int));            rec->saved_max * sizeof(int));
           offset_top = rec->save_offset_top;
         ecode = rec->after_call;          ecode = rec->after_call;
         ims = original_ims;          ims = original_ims;
         break;          break;
Line 1331  for (;;) Line 1664  for (;;)
     /* Start of subject unless notbol, or after internal newline if multiline */      /* Start of subject unless notbol, or after internal newline if multiline */
   
     case OP_CIRC:      case OP_CIRC:
     if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);      if (md->notbol && eptr == md->start_subject) MRRETURN(MATCH_NOMATCH);
     if ((ims & PCRE_MULTILINE) != 0)      if ((ims & PCRE_MULTILINE) != 0)
       {        {
       if (eptr != md->start_subject &&        if (eptr != md->start_subject &&
           (eptr == md->end_subject || !WAS_NEWLINE(eptr)))            (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
       ecode++;        ecode++;
       break;        break;
       }        }
Line 1345  for (;;) Line 1678  for (;;)
     /* Start of subject assertion */      /* Start of subject assertion */
   
     case OP_SOD:      case OP_SOD:
     if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);      if (eptr != md->start_subject) MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     /* Start of match assertion */      /* Start of match assertion */
   
     case OP_SOM:      case OP_SOM:
     if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);      if (eptr != md->start_subject + md->start_offset) MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
Line 1370  for (;;) Line 1703  for (;;)
     if ((ims & PCRE_MULTILINE) != 0)      if ((ims & PCRE_MULTILINE) != 0)
       {        {
       if (eptr < md->end_subject)        if (eptr < md->end_subject)
         { if (!IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); }          { if (!IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); }
       else        else
         { if (md->noteol) RRETURN(MATCH_NOMATCH); }          {
           if (md->noteol) MRRETURN(MATCH_NOMATCH);
           SCHECK_PARTIAL();
           }
       ecode++;        ecode++;
       break;        break;
       }        }
     else      else  /* Not multiline */
       {        {
       if (md->noteol) RRETURN(MATCH_NOMATCH);        if (md->noteol) MRRETURN(MATCH_NOMATCH);
       if (!md->endonly)        if (!md->endonly) goto ASSERT_NL_OR_EOS;
         {  
         if (eptr != md->end_subject &&  
             (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))  
           RRETURN(MATCH_NOMATCH);  
         ecode++;  
         break;  
         }  
       }        }
   
     /* ... else fall through for endonly */      /* ... else fall through for endonly */
   
     /* End of subject assertion (\z) */      /* End of subject assertion (\z) */
   
     case OP_EOD:      case OP_EOD:
     if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr < md->end_subject) MRRETURN(MATCH_NOMATCH);
       SCHECK_PARTIAL();
     ecode++;      ecode++;
     break;      break;
   
     /* End of subject or ending \n assertion (\Z) */      /* End of subject or ending \n assertion (\Z) */
   
     case OP_EODN:      case OP_EODN:
     if (eptr != md->end_subject &&      ASSERT_NL_OR_EOS:
       if (eptr < md->end_subject &&
         (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))          (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
   
       /* Either at end of string or \n before end. */
   
       SCHECK_PARTIAL();
     ecode++;      ecode++;
     break;      break;
   
Line 1414  for (;;) Line 1750  for (;;)
   
       /* Find out if the previous and current characters are "word" characters.        /* Find out if the previous and current characters are "word" characters.
       It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to        It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to
       be "non-word" characters. */        be "non-word" characters. Remember the earliest consulted character for
         partial matching. */
   
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
       if (utf8)        if (utf8)
         {          {
           /* Get status of previous character */
   
         if (eptr == md->start_subject) prev_is_word = FALSE; else          if (eptr == md->start_subject) prev_is_word = FALSE; else
           {            {
           const uschar *lastptr = eptr - 1;            USPTR lastptr = eptr - 1;
           while((*lastptr & 0xc0) == 0x80) lastptr--;            while((*lastptr & 0xc0) == 0x80) lastptr--;
             if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
           GETCHAR(c, lastptr);            GETCHAR(c, lastptr);
   #ifdef SUPPORT_UCP
             if (md->use_ucp)
               {
               if (c == '_') prev_is_word = TRUE; else
                 {
                 int cat = UCD_CATEGORY(c);
                 prev_is_word = (cat == ucp_L || cat == ucp_N);
                 }
               }
             else
   #endif
           prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;            prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
           }            }
         if (eptr >= md->end_subject) cur_is_word = FALSE; else  
           /* Get status of next character */
   
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
             cur_is_word = FALSE;
             }
           else
           {            {
           GETCHAR(c, eptr);            GETCHAR(c, eptr);
   #ifdef SUPPORT_UCP
             if (md->use_ucp)
               {
               if (c == '_') cur_is_word = TRUE; else
                 {
                 int cat = UCD_CATEGORY(c);
                 cur_is_word = (cat == ucp_L || cat == ucp_N);
                 }
               }
             else
   #endif
           cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;            cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
           }            }
         }          }
       else        else
 #endif  #endif
   
       /* More streamlined when not in UTF-8 mode */        /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for
         consistency with the behaviour of \w we do use it in this case. */
   
         {          {
         prev_is_word = (eptr != md->start_subject) &&          /* Get status of previous character */
           ((md->ctypes[eptr[-1]] & ctype_word) != 0);  
         cur_is_word = (eptr < md->end_subject) &&          if (eptr == md->start_subject) prev_is_word = FALSE; else
           ((md->ctypes[*eptr] & ctype_word) != 0);            {
             if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1;
   #ifdef SUPPORT_UCP
             if (md->use_ucp)
               {
               c = eptr[-1];
               if (c == '_') prev_is_word = TRUE; else
                 {
                 int cat = UCD_CATEGORY(c);
                 prev_is_word = (cat == ucp_L || cat == ucp_N);
                 }
               }
             else
   #endif
             prev_is_word = ((md->ctypes[eptr[-1]] & ctype_word) != 0);
             }
   
           /* Get status of next character */
   
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
             cur_is_word = FALSE;
             }
           else
   #ifdef SUPPORT_UCP
           if (md->use_ucp)
             {
             c = *eptr;
             if (c == '_') cur_is_word = TRUE; else
               {
               int cat = UCD_CATEGORY(c);
               cur_is_word = (cat == ucp_L || cat == ucp_N);
               }
             }
           else
   #endif
           cur_is_word = ((md->ctypes[*eptr] & ctype_word) != 0);
         }          }
   
       /* Now see if the situation is what we want */        /* Now see if the situation is what we want */
   
       if ((*ecode++ == OP_WORD_BOUNDARY)?        if ((*ecode++ == OP_WORD_BOUNDARY)?
            cur_is_word == prev_is_word : cur_is_word != prev_is_word)             cur_is_word == prev_is_word : cur_is_word != prev_is_word)
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
       }        }
     break;      break;
   
     /* Match a single character type; inline for speed */      /* Match a single character type; inline for speed */
   
     case OP_ANY:      case OP_ANY:
     if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);      if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH);
     /* Fall through */      /* Fall through */
   
     case OP_ALLANY:      case OP_ALLANY:
     if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr++ >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;      if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
     ecode++;      ecode++;
     break;      break;
Line 1468  for (;;) Line 1880  for (;;)
     any byte, even newline, independent of the setting of PCRE_DOTALL. */      any byte, even newline, independent of the setting of PCRE_DOTALL. */
   
     case OP_ANYBYTE:      case OP_ANYBYTE:
     if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr++ >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     ecode++;      ecode++;
     break;      break;
   
     case OP_NOT_DIGIT:      case OP_NOT_DIGIT:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if (      if (
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 1481  for (;;) Line 1901  for (;;)
 #endif  #endif
        (md->ctypes[c] & ctype_digit) != 0         (md->ctypes[c] & ctype_digit) != 0
        )         )
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     case OP_DIGIT:      case OP_DIGIT:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if (      if (
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 1494  for (;;) Line 1918  for (;;)
 #endif  #endif
        (md->ctypes[c] & ctype_digit) == 0         (md->ctypes[c] & ctype_digit) == 0
        )         )
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     case OP_NOT_WHITESPACE:      case OP_NOT_WHITESPACE:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if (      if (
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 1507  for (;;) Line 1935  for (;;)
 #endif  #endif
        (md->ctypes[c] & ctype_space) != 0         (md->ctypes[c] & ctype_space) != 0
        )         )
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     case OP_WHITESPACE:      case OP_WHITESPACE:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if (      if (
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 1520  for (;;) Line 1952  for (;;)
 #endif  #endif
        (md->ctypes[c] & ctype_space) == 0         (md->ctypes[c] & ctype_space) == 0
        )         )
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     case OP_NOT_WORDCHAR:      case OP_NOT_WORDCHAR:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if (      if (
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 1533  for (;;) Line 1969  for (;;)
 #endif  #endif
        (md->ctypes[c] & ctype_word) != 0         (md->ctypes[c] & ctype_word) != 0
        )         )
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     case OP_WORDCHAR:      case OP_WORDCHAR:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if (      if (
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 1546  for (;;) Line 1986  for (;;)
 #endif  #endif
        (md->ctypes[c] & ctype_word) == 0         (md->ctypes[c] & ctype_word) == 0
        )         )
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
     ecode++;      ecode++;
     break;      break;
   
     case OP_ANYNL:      case OP_ANYNL:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
       default: RRETURN(MATCH_NOMATCH);        default: MRRETURN(MATCH_NOMATCH);
       case 0x000d:        case 0x000d:
       if (eptr < md->end_subject && *eptr == 0x0a) eptr++;        if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
       break;        break;
Line 1568  for (;;) Line 2012  for (;;)
       case 0x0085:        case 0x0085:
       case 0x2028:        case 0x2028:
       case 0x2029:        case 0x2029:
       if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);        if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
       break;        break;
       }        }
     ecode++;      ecode++;
     break;      break;
   
     case OP_NOT_HSPACE:      case OP_NOT_HSPACE:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
Line 1599  for (;;) Line 2047  for (;;)
       case 0x202f:    /* NARROW NO-BREAK SPACE */        case 0x202f:    /* NARROW NO-BREAK SPACE */
       case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */        case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
       case 0x3000:    /* IDEOGRAPHIC SPACE */        case 0x3000:    /* IDEOGRAPHIC SPACE */
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
       }        }
     ecode++;      ecode++;
     break;      break;
   
     case OP_HSPACE:      case OP_HSPACE:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
       default: RRETURN(MATCH_NOMATCH);        default: MRRETURN(MATCH_NOMATCH);
       case 0x09:      /* HT */        case 0x09:      /* HT */
       case 0x20:      /* SPACE */        case 0x20:      /* SPACE */
       case 0xa0:      /* NBSP */        case 0xa0:      /* NBSP */
Line 1635  for (;;) Line 2087  for (;;)
     break;      break;
   
     case OP_NOT_VSPACE:      case OP_NOT_VSPACE:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
Line 1647  for (;;) Line 2103  for (;;)
       case 0x85:      /* NEL */        case 0x85:      /* NEL */
       case 0x2028:    /* LINE SEPARATOR */        case 0x2028:    /* LINE SEPARATOR */
       case 0x2029:    /* PARAGRAPH SEPARATOR */        case 0x2029:    /* PARAGRAPH SEPARATOR */
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
       }        }
     ecode++;      ecode++;
     break;      break;
   
     case OP_VSPACE:      case OP_VSPACE:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     switch(c)      switch(c)
       {        {
       default: RRETURN(MATCH_NOMATCH);        default: MRRETURN(MATCH_NOMATCH);
       case 0x0a:      /* LF */        case 0x0a:      /* LF */
       case 0x0b:      /* VT */        case 0x0b:      /* VT */
       case 0x0c:      /* FF */        case 0x0c:      /* FF */
Line 1676  for (;;) Line 2136  for (;;)
   
     case OP_PROP:      case OP_PROP:
     case OP_NOTPROP:      case OP_NOTPROP:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
       {        {
       const ucd_record * prop = GET_UCD(c);        const ucd_record *prop = GET_UCD(c);
   
       switch(ecode[1])        switch(ecode[1])
         {          {
         case PT_ANY:          case PT_ANY:
         if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);          if (op == OP_NOTPROP) MRRETURN(MATCH_NOMATCH);
         break;          break;
   
         case PT_LAMP:          case PT_LAMP:
         if ((prop->chartype == ucp_Lu ||          if ((prop->chartype == ucp_Lu ||
              prop->chartype == ucp_Ll ||               prop->chartype == ucp_Ll ||
              prop->chartype == ucp_Lt) == (op == OP_NOTPROP))               prop->chartype == ucp_Lt) == (op == OP_NOTPROP))
           RRETURN(MATCH_NOMATCH);            MRRETURN(MATCH_NOMATCH);
          break;          break;
   
         case PT_GC:          case PT_GC:
         if ((ecode[2] != _pcre_ucp_gentype[prop->chartype]) == (op == OP_PROP))          if ((ecode[2] != _pcre_ucp_gentype[prop->chartype]) == (op == OP_PROP))
           RRETURN(MATCH_NOMATCH);            MRRETURN(MATCH_NOMATCH);
         break;          break;
   
         case PT_PC:          case PT_PC:
         if ((ecode[2] != prop->chartype) == (op == OP_PROP))          if ((ecode[2] != prop->chartype) == (op == OP_PROP))
           RRETURN(MATCH_NOMATCH);            MRRETURN(MATCH_NOMATCH);
         break;          break;
   
         case PT_SC:          case PT_SC:
         if ((ecode[2] != prop->script) == (op == OP_PROP))          if ((ecode[2] != prop->script) == (op == OP_PROP))
           RRETURN(MATCH_NOMATCH);            MRRETURN(MATCH_NOMATCH);
           break;
   
           /* These are specials */
   
           case PT_ALNUM:
           if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
                _pcre_ucp_gentype[prop->chartype] == ucp_N) == (op == OP_NOTPROP))
             MRRETURN(MATCH_NOMATCH);
           break;
   
           case PT_SPACE:    /* Perl space */
           if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
                c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
                  == (op == OP_NOTPROP))
             MRRETURN(MATCH_NOMATCH);
         break;          break;
   
           case PT_PXSPACE:  /* POSIX space */
           if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z ||
                c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
                c == CHAR_FF || c == CHAR_CR)
                  == (op == OP_NOTPROP))
             MRRETURN(MATCH_NOMATCH);
           break;
   
           case PT_WORD:
           if ((_pcre_ucp_gentype[prop->chartype] == ucp_L ||
                _pcre_ucp_gentype[prop->chartype] == ucp_N ||
                c == CHAR_UNDERSCORE) == (op == OP_NOTPROP))
             MRRETURN(MATCH_NOMATCH);
           break;
   
           /* This should never occur */
   
         default:          default:
         RRETURN(PCRE_ERROR_INTERNAL);          RRETURN(PCRE_ERROR_INTERNAL);
         }          }
Line 1721  for (;;) Line 2217  for (;;)
     is in the binary; otherwise a compile-time error occurs. */      is in the binary; otherwise a compile-time error occurs. */
   
     case OP_EXTUNI:      case OP_EXTUNI:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
       {        {
       int category = UCD_CATEGORY(c);        int category = UCD_CATEGORY(c);
       if (category == ucp_M) RRETURN(MATCH_NOMATCH);        if (category == ucp_M) MRRETURN(MATCH_NOMATCH);
       while (eptr < md->end_subject)        while (eptr < md->end_subject)
         {          {
         int len = 1;          int len = 1;
Line 1770  for (;;) Line 2270  for (;;)
       referenced subpattern. */        referenced subpattern. */
   
       if (offset >= offset_top || md->offset_vector[offset] < 0)        if (offset >= offset_top || md->offset_vector[offset] < 0)
         length = (md->jscript_compat)? 0 : md->end_subject - eptr + 1;          length = (md->jscript_compat)? 0 : (int)(md->end_subject - eptr + 1);
       else        else
         length = md->offset_vector[offset+1] - md->offset_vector[offset];          length = md->offset_vector[offset+1] - md->offset_vector[offset];
   
Line 1801  for (;;) Line 2301  for (;;)
         break;          break;
   
         default:               /* No repeat follows */          default:               /* No repeat follows */
         if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);          if (!match_ref(offset, eptr, length, md, ims))
             {
             CHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
         eptr += length;          eptr += length;
         continue;              /* With the main loop */          continue;              /* With the main loop */
         }          }
Line 1817  for (;;) Line 2321  for (;;)
   
       for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
         {          {
         if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);          if (!match_ref(offset, eptr, length, md, ims))
             {
             CHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
         eptr += length;          eptr += length;
         }          }
   
Line 1834  for (;;) Line 2342  for (;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || !match_ref(offset, eptr, length, md, ims))            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             RRETURN(MATCH_NOMATCH);            if (!match_ref(offset, eptr, length, md, ims))
               {
               CHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           eptr += length;            eptr += length;
           }            }
         /* Control never gets here */          /* Control never gets here */
Line 1848  for (;;) Line 2360  for (;;)
         pp = eptr;          pp = eptr;
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
           if (!match_ref(offset, eptr, length, md, ims)) break;            if (!match_ref(offset, eptr, length, md, ims))
               {
               CHECK_PARTIAL();
               break;
               }
           eptr += length;            eptr += length;
           }            }
         while (eptr >= pp)          while (eptr >= pp)
Line 1857  for (;;) Line 2373  for (;;)
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           eptr -= length;            eptr -= length;
           }            }
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
       }        }
     /* Control never gets here */      /* Control never gets here */
   
   
   
     /* Match a bit-mapped character class, possibly repeatedly. This op code is      /* Match a bit-mapped character class, possibly repeatedly. This op code is
     used when all the characters in the class have values in the range 0-255,      used when all the characters in the class have values in the range 0-255,
     and either the matching is caseful, or the characters are in the range      and either the matching is caseful, or the characters are in the range
Line 1918  for (;;) Line 2432  for (;;)
         {          {
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           if (c > 255)            if (c > 255)
             {              {
             if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);              if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH);
             }              }
           else            else
             {              {
             if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);              if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         }          }
Line 1936  for (;;) Line 2454  for (;;)
         {          {
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           c = *eptr++;            c = *eptr++;
           if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);            if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
           }            }
         }          }
   
Line 1960  for (;;) Line 2482  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
             if (c > 255)              if (c > 255)
               {                {
               if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);                if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH);
               }                }
             else              else
               {                {
               if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);                if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
               }                }
             }              }
           }            }
Line 1980  for (;;) Line 2507  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             c = *eptr++;              c = *eptr++;
             if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);              if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         /* Control never gets here */          /* Control never gets here */
Line 2001  for (;;) Line 2533  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c > 255)              if (c > 255)
               {                {
Line 2027  for (;;) Line 2563  for (;;)
           {            {
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             c = *eptr;              c = *eptr;
             if ((data[c/8] & (1 << (c&7))) == 0) break;              if ((data[c/8] & (1 << (c&7))) == 0) break;
             eptr++;              eptr++;
Line 2040  for (;;) Line 2580  for (;;)
             }              }
           }            }
   
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
       }        }
     /* Control never gets here */      /* Control never gets here */
   
   
     /* Match an extended character class. This opcode is encountered only      /* Match an extended character class. This opcode is encountered only
     in UTF-8 mode, because that's the only time it is compiled. */      when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8
       mode, because Unicode properties are supported in non-UTF-8 mode. */
   
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
     case OP_XCLASS:      case OP_XCLASS:
Line 2088  for (;;) Line 2629  for (;;)
   
       for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
         {          {
         if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);          if (eptr >= md->end_subject)
         GETCHARINC(c, eptr);            {
         if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);            SCHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
           GETCHARINCTEST(c, eptr);
           if (!_pcre_xclass(c, data)) MRRETURN(MATCH_NOMATCH);
         }          }
   
       /* If max == min we can continue with the main loop without the        /* If max == min we can continue with the main loop without the
Line 2107  for (;;) Line 2652  for (;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (fi >= max) MRRETURN(MATCH_NOMATCH);
           GETCHARINC(c, eptr);            if (eptr >= md->end_subject)
           if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);              {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             GETCHARINCTEST(c, eptr);
             if (!_pcre_xclass(c, data)) MRRETURN(MATCH_NOMATCH);
           }            }
         /* Control never gets here */          /* Control never gets here */
         }          }
Line 2122  for (;;) Line 2672  for (;;)
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
           int len = 1;            int len = 1;
           if (eptr >= md->end_subject) break;            if (eptr >= md->end_subject)
           GETCHARLEN(c, eptr, len);              {
               SCHECK_PARTIAL();
               break;
               }
             GETCHARLENTEST(c, eptr, len);
           if (!_pcre_xclass(c, data)) break;            if (!_pcre_xclass(c, data)) break;
           eptr += len;            eptr += len;
           }            }
Line 2134  for (;;) Line 2688  for (;;)
           if (eptr-- == pp) break;        /* Stop if tried at original pos */            if (eptr-- == pp) break;        /* Stop if tried at original pos */
           if (utf8) BACKCHAR(eptr);            if (utf8) BACKCHAR(eptr);
           }            }
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
   
       /* Control never gets here */        /* Control never gets here */
Line 2150  for (;;) Line 2704  for (;;)
       length = 1;        length = 1;
       ecode++;        ecode++;
       GETCHARLEN(fc, ecode, length);        GETCHARLEN(fc, ecode, length);
       if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);        if (length > md->end_subject - eptr)
       while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);          {
           CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
           MRRETURN(MATCH_NOMATCH);
           }
         while (length-- > 0) if (*ecode++ != *eptr++) MRRETURN(MATCH_NOMATCH);
       }        }
     else      else
 #endif  #endif
   
     /* Non-UTF-8 mode */      /* Non-UTF-8 mode */
       {        {
       if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);        if (md->end_subject - eptr < 1)
       if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);          {
           SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
           MRRETURN(MATCH_NOMATCH);
           }
         if (ecode[1] != *eptr++) MRRETURN(MATCH_NOMATCH);
       ecode += 2;        ecode += 2;
       }        }
     break;      break;
Line 2174  for (;;) Line 2736  for (;;)
       ecode++;        ecode++;
       GETCHARLEN(fc, ecode, length);        GETCHARLEN(fc, ecode, length);
   
       if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);        if (length > md->end_subject - eptr)
           {
           CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
           MRRETURN(MATCH_NOMATCH);
           }
   
       /* If the pattern character's value is < 128, we have only one byte, and        /* If the pattern character's value is < 128, we have only one byte, and
       can use the fast lookup table. */        can use the fast lookup table. */
   
       if (fc < 128)        if (fc < 128)
         {          {
         if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);          if (md->lcc[*ecode++] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
         }          }
   
       /* Otherwise we must pick up the subject character */        /* Otherwise we must pick up the subject character */
Line 2200  for (;;) Line 2766  for (;;)
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
           if (dc != UCD_OTHERCASE(fc))            if (dc != UCD_OTHERCASE(fc))
 #endif  #endif
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
           }            }
         }          }
       }        }
Line 2209  for (;;) Line 2775  for (;;)
   
     /* Non-UTF-8 mode */      /* Non-UTF-8 mode */
       {        {
       if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);        if (md->end_subject - eptr < 1)
       if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);          {
           SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
           MRRETURN(MATCH_NOMATCH);
           }
         if (md->lcc[ecode[1]] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
       ecode += 2;        ecode += 2;
       }        }
     break;      break;
Line 2263  for (;;) Line 2833  for (;;)
     case OP_MINQUERY:      case OP_MINQUERY:
     c = *ecode++ - OP_STAR;      c = *ecode++ - OP_STAR;
     minimize = (c & 1) != 0;      minimize = (c & 1) != 0;
   
     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;
   
     /* Common code for all repeated single-character matches. We can give      /* Common code for all repeated single-character matches. */
     up quickly if there are fewer than the minimum number of characters left in  
     the subject. */  
   
     REPEATCHAR:      REPEATCHAR:
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
Line 2278  for (;;) Line 2847  for (;;)
       length = 1;        length = 1;
       charptr = ecode;        charptr = ecode;
       GETCHARLEN(fc, ecode, length);        GETCHARLEN(fc, ecode, length);
       if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);  
       ecode += length;        ecode += length;
   
       /* Handle multibyte character matching specially here. There is        /* Handle multibyte character matching specially here. There is
Line 2296  for (;;) Line 2864  for (;;)
   
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (memcmp(eptr, charptr, length) == 0) eptr += length;            if (eptr <= md->end_subject - length &&
               memcmp(eptr, charptr, length) == 0) eptr += length;
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
           /* Need braces because of following else */            else if (oclength > 0 &&
           else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }                     eptr <= md->end_subject - oclength &&
                      memcmp(eptr, occhars, oclength) == 0) eptr += oclength;
   #endif  /* SUPPORT_UCP */
           else            else
             {              {
             if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);              CHECK_PARTIAL();
             eptr += oclength;              MRRETURN(MATCH_NOMATCH);
             }              }
 #else   /* without SUPPORT_UCP */  
           else { RRETURN(MATCH_NOMATCH); }  
 #endif  /* SUPPORT_UCP */  
           }            }
   
         if (min == max) continue;          if (min == max) continue;
Line 2318  for (;;) Line 2886  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (memcmp(eptr, charptr, length) == 0) eptr += length;              if (eptr <= md->end_subject - length &&
                 memcmp(eptr, charptr, length) == 0) eptr += length;
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
             /* Need braces because of following else */              else if (oclength > 0 &&
             else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }                       eptr <= md->end_subject - oclength &&
                        memcmp(eptr, occhars, oclength) == 0) eptr += oclength;
   #endif  /* SUPPORT_UCP */
             else              else
               {                {
               if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);                CHECK_PARTIAL();
               eptr += oclength;                MRRETURN(MATCH_NOMATCH);
               }                }
 #else   /* without SUPPORT_UCP */  
             else { RRETURN (MATCH_NOMATCH); }  
 #endif  /* SUPPORT_UCP */  
             }              }
           /* Control never gets here */            /* Control never gets here */
           }            }
Line 2340  for (;;) Line 2908  for (;;)
           pp = eptr;            pp = eptr;
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr > md->end_subject - length) break;              if (eptr <= md->end_subject - length &&
             if (memcmp(eptr, charptr, length) == 0) eptr += length;                  memcmp(eptr, charptr, length) == 0) eptr += length;
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
             else if (oclength == 0) break;              else if (oclength > 0 &&
                        eptr <= md->end_subject - oclength &&
                        memcmp(eptr, occhars, oclength) == 0) eptr += oclength;
   #endif  /* SUPPORT_UCP */
             else              else
               {                {
               if (memcmp(eptr, occhars, oclength) != 0) break;                CHECK_PARTIAL();
               eptr += oclength;                break;
               }                }
 #else   /* without SUPPORT_UCP */  
             else break;  
 #endif  /* SUPPORT_UCP */  
             }              }
   
           if (possessive) continue;            if (possessive) continue;
   
           for(;;)            for(;;)
            {              {
            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);
            if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
            if (eptr == pp) RRETURN(MATCH_NOMATCH);              if (eptr == pp) { MRRETURN(MATCH_NOMATCH); }
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
            eptr--;              eptr--;
            BACKCHAR(eptr);              BACKCHAR(eptr);
 #else   /* without SUPPORT_UCP */  #else   /* without SUPPORT_UCP */
            eptr -= length;              eptr -= length;
 #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
            }              }
           }            }
         /* Control never gets here */          /* Control never gets here */
         }          }
Line 2379  for (;;) Line 2948  for (;;)
 #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF8 */
   
     /* When not in UTF-8 mode, load a single-byte character. */      /* When not in UTF-8 mode, load a single-byte character. */
       {  
       if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);      fc = *ecode++;
       fc = *ecode++;  
       }  
   
     /* The value of fc at this point is always less than 256, though we may or      /* The value of fc at this point is always less than 256, though we may or
     may not be in UTF-8 mode. The code is duplicated for the caseless and      may not be in UTF-8 mode. The code is duplicated for the caseless and
Line 2400  for (;;) Line 2967  for (;;)
       {        {
       fc = md->lcc[fc];        fc = md->lcc[fc];
       for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
         if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);          {
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
           if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
           }
       if (min == max) continue;        if (min == max) continue;
       if (minimize)        if (minimize)
         {          {
Line 2408  for (;;) Line 2982  for (;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || eptr >= md->end_subject ||            if (fi >= max) MRRETURN(MATCH_NOMATCH);
               fc != md->lcc[*eptr++])            if (eptr >= md->end_subject)
             RRETURN(MATCH_NOMATCH);              {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
           }            }
         /* Control never gets here */          /* Control never gets here */
         }          }
Line 2419  for (;;) Line 2997  for (;;)
         pp = eptr;          pp = eptr;
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
           if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break;            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               break;
               }
             if (fc != md->lcc[*eptr]) break;
           eptr++;            eptr++;
           }            }
   
         if (possessive) continue;          if (possessive) continue;
   
         while (eptr >= pp)          while (eptr >= pp)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);
           eptr--;            eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }            }
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
       /* Control never gets here */        /* Control never gets here */
       }        }
Line 2438  for (;;) Line 3023  for (;;)
   
     else      else
       {        {
       for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH);        for (i = 1; i <= min; i++)
           {
           if (eptr >= md->end_subject)
             {
             SCHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
           if (fc != *eptr++) MRRETURN(MATCH_NOMATCH);
           }
   
       if (min == max) continue;        if (min == max) continue;
   
       if (minimize)        if (minimize)
         {          {
         for (fi = min;; fi++)          for (fi = min;; fi++)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || eptr >= md->end_subject || fc != *eptr++)            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (fc != *eptr++) MRRETURN(MATCH_NOMATCH);
           }            }
         /* Control never gets here */          /* Control never gets here */
         }          }
Line 2456  for (;;) Line 3056  for (;;)
         pp = eptr;          pp = eptr;
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
           if (eptr >= md->end_subject || fc != *eptr) break;            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               break;
               }
             if (fc != *eptr) break;
           eptr++;            eptr++;
           }            }
         if (possessive) continue;          if (possessive) continue;
   
         while (eptr >= pp)          while (eptr >= pp)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);
           eptr--;            eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }            }
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
       }        }
     /* Control never gets here */      /* Control never gets here */
Line 2475  for (;;) Line 3081  for (;;)
     checking can be multibyte. */      checking can be multibyte. */
   
     case OP_NOT:      case OP_NOT:
     if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
         {
         SCHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
         }
     ecode++;      ecode++;
     GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
     if ((ims & PCRE_CASELESS) != 0)      if ((ims & PCRE_CASELESS) != 0)
Line 2484  for (;;) Line 3094  for (;;)
       if (c < 256)        if (c < 256)
 #endif  #endif
       c = md->lcc[c];        c = md->lcc[c];
       if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH);        if (md->lcc[*ecode++] == c) MRRETURN(MATCH_NOMATCH);
       }        }
     else      else
       {        {
       if (*ecode++ == c) RRETURN(MATCH_NOMATCH);        if (*ecode++ == c) MRRETURN(MATCH_NOMATCH);
       }        }
     break;      break;
   
Line 2552  for (;;) Line 3162  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-byte matches. We can give up quickly      /* Common code for all repeated single-byte matches. */
     if there are fewer than the minimum number of bytes left in the  
     subject. */  
   
     REPEATNOTCHAR:      REPEATNOTCHAR:
     if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);  
     fc = *ecode++;      fc = *ecode++;
   
     /* The code is duplicated for the caseless and caseful cases, for speed,      /* The code is duplicated for the caseless and caseful cases, for speed,
Line 2582  for (;;) Line 3189  for (;;)
         register unsigned int d;          register unsigned int d;
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(d, eptr);            GETCHARINC(d, eptr);
           if (d < 256) d = md->lcc[d];            if (d < 256) d = md->lcc[d];
           if (fc == d) RRETURN(MATCH_NOMATCH);            if (fc == d) MRRETURN(MATCH_NOMATCH);
           }            }
         }          }
       else        else
Line 2593  for (;;) Line 3205  for (;;)
       /* Not UTF-8 mode */        /* Not UTF-8 mode */
         {          {
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
             }
         }          }
   
       if (min == max) continue;        if (min == max) continue;
Line 2609  for (;;) Line 3228  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINC(d, eptr);              GETCHARINC(d, eptr);
             if (d < 256) d = md->lcc[d];              if (d < 256) d = md->lcc[d];
             if (fc == d) RRETURN(MATCH_NOMATCH);              if (fc == d) MRRETURN(MATCH_NOMATCH);
   
             }              }
           }            }
         else          else
Line 2624  for (;;) Line 3247  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++])              if (fi >= max) MRRETURN(MATCH_NOMATCH);
               RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         /* Control never gets here */          /* Control never gets here */
Line 2645  for (;;) Line 3273  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(d, eptr, len);              GETCHARLEN(d, eptr, len);
             if (d < 256) d = md->lcc[d];              if (d < 256) d = md->lcc[d];
             if (fc == d) break;              if (fc == d) break;
Line 2666  for (;;) Line 3298  for (;;)
           {            {
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || fc == md->lcc[*eptr]) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               if (fc == md->lcc[*eptr]) break;
             eptr++;              eptr++;
             }              }
           if (possessive) continue;            if (possessive) continue;
Line 2678  for (;;) Line 3315  for (;;)
             }              }
           }            }
   
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
       /* Control never gets here */        /* Control never gets here */
       }        }
Line 2694  for (;;) Line 3331  for (;;)
         register unsigned int d;          register unsigned int d;
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(d, eptr);            GETCHARINC(d, eptr);
           if (fc == d) RRETURN(MATCH_NOMATCH);            if (fc == d) MRRETURN(MATCH_NOMATCH);
           }            }
         }          }
       else        else
Line 2703  for (;;) Line 3345  for (;;)
       /* Not UTF-8 mode */        /* Not UTF-8 mode */
         {          {
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           if (fc == *eptr++) RRETURN(MATCH_NOMATCH);            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (fc == *eptr++) MRRETURN(MATCH_NOMATCH);
             }
         }          }
   
       if (min == max) continue;        if (min == max) continue;
Line 2719  for (;;) Line 3368  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINC(d, eptr);              GETCHARINC(d, eptr);
             if (fc == d) RRETURN(MATCH_NOMATCH);              if (fc == d) MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         else          else
Line 2732  for (;;) Line 3386  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject || fc == *eptr++)              if (fi >= max) MRRETURN(MATCH_NOMATCH);
               RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               if (fc == *eptr++) MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         /* Control never gets here */          /* Control never gets here */
Line 2753  for (;;) Line 3412  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(d, eptr, len);              GETCHARLEN(d, eptr, len);
             if (fc == d) break;              if (fc == d) break;
             eptr += len;              eptr += len;
Line 2773  for (;;) Line 3436  for (;;)
           {            {
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || fc == *eptr) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               if (fc == *eptr) break;
             eptr++;              eptr++;
             }              }
           if (possessive) continue;            if (possessive) continue;
Line 2785  for (;;) Line 3453  for (;;)
             }              }
           }            }
   
         RRETURN(MATCH_NOMATCH);          MRRETURN(MATCH_NOMATCH);
         }          }
       }        }
     /* Control never gets here */      /* Control never gets here */
Line 2867  for (;;) Line 3535  for (;;)
   
     /* First, ensure the minimum number of matches are present. Use inline      /* First, ensure the minimum number of matches are present. Use inline
     code for maximizing the speed, and do the type test once at the start      code for maximizing the speed, and do the type test once at the start
     (i.e. keep it out of the loop). Also we can test that there are at least      (i.e. keep it out of the loop). Separate the UTF-8 code completely as that
     the minimum number of bytes before we start. This isn't as effective in  
     UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that  
     is tidier. Also separate the UCP code, which can be the same for both UTF-8      is tidier. Also separate the UCP code, which can be the same for both UTF-8
     and single-bytes. */      and single-bytes. */
   
     if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);  
     if (min > 0)      if (min > 0)
       {        {
 #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
Line 2882  for (;;) Line 3547  for (;;)
         switch(prop_type)          switch(prop_type)
           {            {
           case PT_ANY:            case PT_ANY:
           if (prop_fail_result) RRETURN(MATCH_NOMATCH);            if (prop_fail_result) MRRETURN(MATCH_NOMATCH);
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
             if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
             }              }
           break;            break;
Line 2893  for (;;) Line 3562  for (;;)
           case PT_LAMP:            case PT_LAMP:
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
             if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == ucp_Lu ||              if ((prop_chartype == ucp_Lu ||
                  prop_chartype == ucp_Ll ||                   prop_chartype == ucp_Ll ||
                  prop_chartype == ucp_Lt) == prop_fail_result)                   prop_chartype == ucp_Lt) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             }              }
           break;            break;
   
           case PT_GC:            case PT_GC:
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
             if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
             prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
             if ((prop_category == prop_value) == prop_fail_result)              if ((prop_category == prop_value) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             }              }
           break;            break;
   
           case PT_PC:            case PT_PC:
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
             if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == prop_value) == prop_fail_result)              if ((prop_chartype == prop_value) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             }              }
           break;            break;
   
           case PT_SC:            case PT_SC:
           for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
             {              {
             if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
             GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
             prop_script = UCD_SCRIPT(c);              prop_script = UCD_SCRIPT(c);
             if ((prop_script == prop_value) == prop_fail_result)              if ((prop_script == prop_value) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
               }
             break;
   
             case PT_ALNUM:
             for (i = 1; i <= min; i++)
               {
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_L || prop_category == ucp_N)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
               }
             break;
   
             case PT_SPACE:    /* Perl space */
             for (i = 1; i <= min; i++)
               {
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                    c == CHAR_FF || c == CHAR_CR)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
               }
             break;
   
             case PT_PXSPACE:  /* POSIX space */
             for (i = 1; i <= min; i++)
               {
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                    c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
             }              }
           break;            break;
   
             case PT_WORD:
             for (i = 1; i <= min; i++)
               {
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_L || prop_category == ucp_N ||
                    c == CHAR_UNDERSCORE)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
               }
             break;
   
             /* This should not occur */
   
           default:            default:
           RRETURN(PCRE_ERROR_INTERNAL);            RRETURN(PCRE_ERROR_INTERNAL);
           }            }
Line 2948  for (;;) Line 3702  for (;;)
         {          {
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINCTEST(c, eptr);            GETCHARINCTEST(c, eptr);
           prop_category = UCD_CATEGORY(c);            prop_category = UCD_CATEGORY(c);
           if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);            if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH);
           while (eptr < md->end_subject)            while (eptr < md->end_subject)
             {              {
             int len = 1;              int len = 1;
             if (!utf8) c = *eptr; else              if (!utf8) c = *eptr;
               {                else { GETCHARLEN(c, eptr, len); }
               GETCHARLEN(c, eptr, len);  
               }  
             prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
             if (prop_category != ucp_M) break;              if (prop_category != ucp_M) break;
             eptr += len;              eptr += len;
Line 2976  for (;;) Line 3733  for (;;)
         case OP_ANY:          case OP_ANY:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject || IS_NEWLINE(eptr))            if (eptr >= md->end_subject)
             RRETURN(MATCH_NOMATCH);              {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
           }            }
Line 2986  for (;;) Line 3747  for (;;)
         case OP_ALLANY:          case OP_ALLANY:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           eptr++;            eptr++;
           while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
           }            }
         break;          break;
   
         case OP_ANYBYTE:          case OP_ANYBYTE:
           if (eptr > md->end_subject - min) MRRETURN(MATCH_NOMATCH);
         eptr += min;          eptr += min;
         break;          break;
   
         case OP_ANYNL:          case OP_ANYNL:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: MRRETURN(MATCH_NOMATCH);
             case 0x000d:              case 0x000d:
             if (eptr < md->end_subject && *eptr == 0x0a) eptr++;              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
             break;              break;
Line 3016  for (;;) Line 3786  for (;;)
             case 0x0085:              case 0x0085:
             case 0x2028:              case 0x2028:
             case 0x2029:              case 0x2029:
             if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);              if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
             break;              break;
             }              }
           }            }
Line 3025  for (;;) Line 3795  for (;;)
         case OP_NOT_HSPACE:          case OP_NOT_HSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
Line 3049  for (;;) Line 3823  for (;;)
             case 0x202f:    /* NARROW NO-BREAK SPACE */              case 0x202f:    /* NARROW NO-BREAK SPACE */
             case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
             case 0x3000:    /* IDEOGRAPHIC SPACE */              case 0x3000:    /* IDEOGRAPHIC SPACE */
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         break;          break;
Line 3057  for (;;) Line 3831  for (;;)
         case OP_HSPACE:          case OP_HSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: MRRETURN(MATCH_NOMATCH);
             case 0x09:      /* HT */              case 0x09:      /* HT */
             case 0x20:      /* SPACE */              case 0x20:      /* SPACE */
             case 0xa0:      /* NBSP */              case 0xa0:      /* NBSP */
Line 3089  for (;;) Line 3867  for (;;)
         case OP_NOT_VSPACE:          case OP_NOT_VSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
Line 3101  for (;;) Line 3883  for (;;)
             case 0x85:      /* NEL */              case 0x85:      /* NEL */
             case 0x2028:    /* LINE SEPARATOR */              case 0x2028:    /* LINE SEPARATOR */
             case 0x2029:    /* PARAGRAPH SEPARATOR */              case 0x2029:    /* PARAGRAPH SEPARATOR */
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         break;          break;
Line 3109  for (;;) Line 3891  for (;;)
         case OP_VSPACE:          case OP_VSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(c)            switch(c)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: MRRETURN(MATCH_NOMATCH);
             case 0x0a:      /* LF */              case 0x0a:      /* LF */
             case 0x0b:      /* VT */              case 0x0b:      /* VT */
             case 0x0c:      /* FF */              case 0x0c:      /* FF */
Line 3129  for (;;) Line 3915  for (;;)
         case OP_NOT_DIGIT:          case OP_NOT_DIGIT:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)            if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
           }            }
         break;          break;
   
         case OP_DIGIT:          case OP_DIGIT:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
              *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)              {
             RRETURN(MATCH_NOMATCH);              SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)
               MRRETURN(MATCH_NOMATCH);
           /* 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 */
           }            }
         break;          break;
Line 3149  for (;;) Line 3943  for (;;)
         case OP_NOT_WHITESPACE:          case OP_NOT_WHITESPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
              (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0))              {
             RRETURN(MATCH_NOMATCH);              SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)
               MRRETURN(MATCH_NOMATCH);
           while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);            while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
           }            }
         break;          break;
Line 3159  for (;;) Line 3957  for (;;)
         case OP_WHITESPACE:          case OP_WHITESPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
              *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)              {
             RRETURN(MATCH_NOMATCH);              SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)
               MRRETURN(MATCH_NOMATCH);
           /* 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 */
           }            }
         break;          break;
Line 3169  for (;;) Line 3971  for (;;)
         case OP_NOT_WORDCHAR:          case OP_NOT_WORDCHAR:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
              (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0))              {
             RRETURN(MATCH_NOMATCH);              SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0)
               MRRETURN(MATCH_NOMATCH);
           while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);            while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
           }            }
         break;          break;
Line 3179  for (;;) Line 3985  for (;;)
         case OP_WORDCHAR:          case OP_WORDCHAR:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
              *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)              {
             RRETURN(MATCH_NOMATCH);              SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)
               MRRETURN(MATCH_NOMATCH);
           /* 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 */
           }            }
         break;          break;
Line 3194  for (;;) Line 4004  for (;;)
 #endif     /* SUPPORT_UTF8 */  #endif     /* SUPPORT_UTF8 */
   
       /* Code for the non-UTF-8 case for minimum matching of operators other        /* Code for the non-UTF-8 case for minimum matching of operators other
       than OP_PROP and OP_NOTPROP. We can assume that there are the minimum        than OP_PROP and OP_NOTPROP. */
       number of bytes present, as this was tested above. */  
   
       switch(ctype)        switch(ctype)
         {          {
         case OP_ANY:          case OP_ANY:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH);
           eptr++;            eptr++;
           }            }
         break;          break;
   
         case OP_ALLANY:          case OP_ALLANY:
           if (eptr > md->end_subject - min)
             {
             SCHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
         eptr += min;          eptr += min;
         break;          break;
   
         case OP_ANYBYTE:          case OP_ANYBYTE:
           if (eptr > md->end_subject - min)
             {
             SCHECK_PARTIAL();
             MRRETURN(MATCH_NOMATCH);
             }
         eptr += min;          eptr += min;
         break;          break;
   
         /* Because of the CRLF case, we can't assume the minimum number of  
         bytes are present in this case. */  
   
         case OP_ANYNL:          case OP_ANYNL:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: MRRETURN(MATCH_NOMATCH);
             case 0x000d:              case 0x000d:
             if (eptr < md->end_subject && *eptr == 0x0a) eptr++;              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
             break;              break;
Line 3234  for (;;) Line 4059  for (;;)
             case 0x000b:              case 0x000b:
             case 0x000c:              case 0x000c:
             case 0x0085:              case 0x0085:
             if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);              if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
             break;              break;
             }              }
           }            }
Line 3243  for (;;) Line 4068  for (;;)
         case OP_NOT_HSPACE:          case OP_NOT_HSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: break;              default: break;
             case 0x09:      /* HT */              case 0x09:      /* HT */
             case 0x20:      /* SPACE */              case 0x20:      /* SPACE */
             case 0xa0:      /* NBSP */              case 0xa0:      /* NBSP */
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         break;          break;
Line 3258  for (;;) Line 4087  for (;;)
         case OP_HSPACE:          case OP_HSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: MRRETURN(MATCH_NOMATCH);
             case 0x09:      /* HT */              case 0x09:      /* HT */
             case 0x20:      /* SPACE */              case 0x20:      /* SPACE */
             case 0xa0:      /* NBSP */              case 0xa0:      /* NBSP */
Line 3273  for (;;) Line 4106  for (;;)
         case OP_NOT_VSPACE:          case OP_NOT_VSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: break;              default: break;
Line 3282  for (;;) Line 4119  for (;;)
             case 0x0c:      /* FF */              case 0x0c:      /* FF */
             case 0x0d:      /* CR */              case 0x0d:      /* CR */
             case 0x85:      /* NEL */              case 0x85:      /* NEL */
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
             }              }
           }            }
         break;          break;
Line 3290  for (;;) Line 4127  for (;;)
         case OP_VSPACE:          case OP_VSPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           {            {
           if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           switch(*eptr++)            switch(*eptr++)
             {              {
             default: RRETURN(MATCH_NOMATCH);              default: MRRETURN(MATCH_NOMATCH);
             case 0x0a:      /* LF */              case 0x0a:      /* LF */
             case 0x0b:      /* VT */              case 0x0b:      /* VT */
             case 0x0c:      /* FF */              case 0x0c:      /* FF */
Line 3306  for (;;) Line 4147  for (;;)
   
         case OP_NOT_DIGIT:          case OP_NOT_DIGIT:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if ((md->ctypes[*eptr++] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH);
             }
         break;          break;
   
         case OP_DIGIT:          case OP_DIGIT:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if ((md->ctypes[*eptr++] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH);
             }
         break;          break;
   
         case OP_NOT_WHITESPACE:          case OP_NOT_WHITESPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if ((md->ctypes[*eptr++] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH);
             }
         break;          break;
   
         case OP_WHITESPACE:          case OP_WHITESPACE:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
           if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);            {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if ((md->ctypes[*eptr++] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH);
             }
         break;          break;
   
         case OP_NOT_WORDCHAR:          case OP_NOT_WORDCHAR:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
             {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           if ((md->ctypes[*eptr++] & ctype_word) != 0)            if ((md->ctypes[*eptr++] & ctype_word) != 0)
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
             }
         break;          break;
   
         case OP_WORDCHAR:          case OP_WORDCHAR:
         for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
             {
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           if ((md->ctypes[*eptr++] & ctype_word) == 0)            if ((md->ctypes[*eptr++] & ctype_word) == 0)
             RRETURN(MATCH_NOMATCH);              MRRETURN(MATCH_NOMATCH);
             }
         break;          break;
   
         default:          default:
Line 3361  for (;;) Line 4244  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
             GETCHARINC(c, eptr);              if (eptr >= md->end_subject)
             if (prop_fail_result) RRETURN(MATCH_NOMATCH);                {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               if (prop_fail_result) MRRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
Line 3372  for (;;) Line 4260  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
             GETCHARINC(c, eptr);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == ucp_Lu ||              if ((prop_chartype == ucp_Lu ||
                  prop_chartype == ucp_Ll ||                   prop_chartype == ucp_Ll ||
                  prop_chartype == ucp_Lt) == prop_fail_result)                   prop_chartype == ucp_Lt) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
Line 3387  for (;;) Line 4280  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
             GETCHARINC(c, eptr);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
             prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
             if ((prop_category == prop_value) == prop_fail_result)              if ((prop_category == prop_value) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
Line 3400  for (;;) Line 4298  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
             GETCHARINC(c, eptr);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
             prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == prop_value) == prop_fail_result)              if ((prop_chartype == prop_value) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
Line 3413  for (;;) Line 4316  for (;;)
             {              {
             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) MRRETURN(MATCH_NOMATCH);
             GETCHARINC(c, eptr);              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
             prop_script = UCD_SCRIPT(c);              prop_script = UCD_SCRIPT(c);
             if ((prop_script == prop_value) == prop_fail_result)              if ((prop_script == prop_value) == prop_fail_result)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
               }
             /* Control never gets here */
   
             case PT_ALNUM:
             for (fi = min;; fi++)
               {
               RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM59);
               if (rrc != MATCH_NOMATCH) RRETURN(rrc);
               if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_L || prop_category == ucp_N)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
             }              }
           /* Control never gets here */            /* Control never gets here */
   
             case PT_SPACE:    /* Perl space */
             for (fi = min;; fi++)
               {
               RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM60);
               if (rrc != MATCH_NOMATCH) RRETURN(rrc);
               if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                    c == CHAR_FF || c == CHAR_CR)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
               }
             /* Control never gets here */
   
             case PT_PXSPACE:  /* POSIX space */
             for (fi = min;; fi++)
               {
               RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM61);
               if (rrc != MATCH_NOMATCH) RRETURN(rrc);
               if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                    c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
               }
             /* Control never gets here */
   
             case PT_WORD:
             for (fi = min;; fi++)
               {
               RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM62);
               if (rrc != MATCH_NOMATCH) RRETURN(rrc);
               if (fi >= max) MRRETURN(MATCH_NOMATCH);
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 MRRETURN(MATCH_NOMATCH);
                 }
               GETCHARINCTEST(c, eptr);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_L ||
                    prop_category == ucp_N ||
                    c == CHAR_UNDERSCORE)
                      == prop_fail_result)
                 MRRETURN(MATCH_NOMATCH);
               }
             /* Control never gets here */
   
             /* This should never occur */
   
           default:            default:
           RRETURN(PCRE_ERROR_INTERNAL);            RRETURN(PCRE_ERROR_INTERNAL);
           }            }
Line 3435  for (;;) Line 4425  for (;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
           GETCHARINCTEST(c, eptr);            GETCHARINCTEST(c, eptr);
           prop_category = UCD_CATEGORY(c);            prop_category = UCD_CATEGORY(c);
           if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);            if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH);
           while (eptr < md->end_subject)            while (eptr < md->end_subject)
             {              {
             int len = 1;              int len = 1;
             if (!utf8) c = *eptr; else              if (!utf8) c = *eptr;
               {                else { GETCHARLEN(c, eptr, len); }
               GETCHARLEN(c, eptr, len);  
               }  
             prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
             if (prop_category != ucp_M) break;              if (prop_category != ucp_M) break;
             eptr += len;              eptr += len;
Line 3464  for (;;) Line 4457  for (;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || eptr >= md->end_subject ||            if (fi >= max) MRRETURN(MATCH_NOMATCH);
                (ctype == OP_ANY && IS_NEWLINE(eptr)))            if (eptr >= md->end_subject)
             RRETURN(MATCH_NOMATCH);              {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (ctype == OP_ANY && IS_NEWLINE(eptr))
               MRRETURN(MATCH_NOMATCH);
           GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
           switch(ctype)            switch(ctype)
             {              {
Line 3479  for (;;) Line 4476  for (;;)
             case OP_ANYNL:              case OP_ANYNL:
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: MRRETURN(MATCH_NOMATCH);
               case 0x000d:                case 0x000d:
               if (eptr < md->end_subject && *eptr == 0x0a) eptr++;                if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
               break;                break;
Line 3491  for (;;) Line 4488  for (;;)
               case 0x0085:                case 0x0085:
               case 0x2028:                case 0x2028:
               case 0x2029:                case 0x2029:
               if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);                if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
               break;                break;
               }                }
             break;              break;
Line 3519  for (;;) Line 4516  for (;;)
               case 0x202f:    /* NARROW NO-BREAK SPACE */                case 0x202f:    /* NARROW NO-BREAK SPACE */
               case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */                case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
               case 0x3000:    /* IDEOGRAPHIC SPACE */                case 0x3000:    /* IDEOGRAPHIC SPACE */
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
               }                }
             break;              break;
   
             case OP_HSPACE:              case OP_HSPACE:
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: MRRETURN(MATCH_NOMATCH);
               case 0x09:      /* HT */                case 0x09:      /* HT */
               case 0x20:      /* SPACE */                case 0x20:      /* SPACE */
               case 0xa0:      /* NBSP */                case 0xa0:      /* NBSP */
Line 3561  for (;;) Line 4558  for (;;)
               case 0x85:      /* NEL */                case 0x85:      /* NEL */
               case 0x2028:    /* LINE SEPARATOR */                case 0x2028:    /* LINE SEPARATOR */
               case 0x2029:    /* PARAGRAPH SEPARATOR */                case 0x2029:    /* PARAGRAPH SEPARATOR */
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
               }                }
             break;              break;
   
             case OP_VSPACE:              case OP_VSPACE:
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: MRRETURN(MATCH_NOMATCH);
               case 0x0a:      /* LF */                case 0x0a:      /* LF */
               case 0x0b:      /* VT */                case 0x0b:      /* VT */
               case 0x0c:      /* FF */                case 0x0c:      /* FF */
Line 3582  for (;;) Line 4579  for (;;)
   
             case OP_NOT_DIGIT:              case OP_NOT_DIGIT:
             if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)              if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_DIGIT:              case OP_DIGIT:
             if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)              if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_NOT_WHITESPACE:              case OP_NOT_WHITESPACE:
             if (c < 256 && (md->ctypes[c] & ctype_space) != 0)              if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_WHITESPACE:              case OP_WHITESPACE:
             if  (c >= 256 || (md->ctypes[c] & ctype_space) == 0)              if  (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_NOT_WORDCHAR:              case OP_NOT_WORDCHAR:
             if (c < 256 && (md->ctypes[c] & ctype_word) != 0)              if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_WORDCHAR:              case OP_WORDCHAR:
             if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)              if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             default:              default:
Line 3623  for (;;) Line 4620  for (;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max || eptr >= md->end_subject ||            if (fi >= max) MRRETURN(MATCH_NOMATCH);
                (ctype == OP_ANY && IS_NEWLINE(eptr)))            if (eptr >= md->end_subject)
             RRETURN(MATCH_NOMATCH);              {
               SCHECK_PARTIAL();
               MRRETURN(MATCH_NOMATCH);
               }
             if (ctype == OP_ANY && IS_NEWLINE(eptr))
               MRRETURN(MATCH_NOMATCH);
           c = *eptr++;            c = *eptr++;
           switch(ctype)            switch(ctype)
             {              {
Line 3638  for (;;) Line 4639  for (;;)
             case OP_ANYNL:              case OP_ANYNL:
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: MRRETURN(MATCH_NOMATCH);
               case 0x000d:                case 0x000d:
               if (eptr < md->end_subject && *eptr == 0x0a) eptr++;                if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
               break;                break;
Line 3649  for (;;) Line 4650  for (;;)
               case 0x000b:                case 0x000b:
               case 0x000c:                case 0x000c:
               case 0x0085:                case 0x0085:
               if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);                if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH);
               break;                break;
               }                }
             break;              break;
Line 3661  for (;;) Line 4662  for (;;)
               case 0x09:      /* HT */                case 0x09:      /* HT */
               case 0x20:      /* SPACE */                case 0x20:      /* SPACE */
               case 0xa0:      /* NBSP */                case 0xa0:      /* NBSP */
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
               }                }
             break;              break;
   
             case OP_HSPACE:              case OP_HSPACE:
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: MRRETURN(MATCH_NOMATCH);
               case 0x09:      /* HT */                case 0x09:      /* HT */
               case 0x20:      /* SPACE */                case 0x20:      /* SPACE */
               case 0xa0:      /* NBSP */                case 0xa0:      /* NBSP */
Line 3685  for (;;) Line 4686  for (;;)
               case 0x0c:      /* FF */                case 0x0c:      /* FF */
               case 0x0d:      /* CR */                case 0x0d:      /* CR */
               case 0x85:      /* NEL */                case 0x85:      /* NEL */
               RRETURN(MATCH_NOMATCH);                MRRETURN(MATCH_NOMATCH);
               }                }
             break;              break;
   
             case OP_VSPACE:              case OP_VSPACE:
             switch(c)              switch(c)
               {                {
               default: RRETURN(MATCH_NOMATCH);                default: MRRETURN(MATCH_NOMATCH);
               case 0x0a:      /* LF */                case 0x0a:      /* LF */
               case 0x0b:      /* VT */                case 0x0b:      /* VT */
               case 0x0c:      /* FF */                case 0x0c:      /* FF */
Line 3703  for (;;) Line 4704  for (;;)
             break;              break;
   
             case OP_NOT_DIGIT:              case OP_NOT_DIGIT:
             if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);              if ((md->ctypes[c] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_DIGIT:              case OP_DIGIT:
             if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);              if ((md->ctypes[c] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_NOT_WHITESPACE:              case OP_NOT_WHITESPACE:
             if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);              if ((md->ctypes[c] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_WHITESPACE:              case OP_WHITESPACE:
             if  ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);              if  ((md->ctypes[c] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_NOT_WORDCHAR:              case OP_NOT_WORDCHAR:
             if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);              if ((md->ctypes[c] & ctype_word) != 0) MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             case OP_WORDCHAR:              case OP_WORDCHAR:
             if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);              if ((md->ctypes[c] & ctype_word) == 0) MRRETURN(MATCH_NOMATCH);
             break;              break;
   
             default:              default:
Line 3751  for (;;) Line 4752  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
             GETCHARLEN(c, eptr, len);                {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
             if (prop_fail_result) break;              if (prop_fail_result) break;
             eptr+= len;              eptr+= len;
             }              }
Line 3762  for (;;) Line 4767  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
             GETCHARLEN(c, eptr, len);                {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
             prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == ucp_Lu ||              if ((prop_chartype == ucp_Lu ||
                  prop_chartype == ucp_Ll ||                   prop_chartype == ucp_Ll ||
Line 3777  for (;;) Line 4786  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
             GETCHARLEN(c, eptr, len);                {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
             prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
             if ((prop_category == prop_value) == prop_fail_result)              if ((prop_category == prop_value) == prop_fail_result)
               break;                break;
Line 3790  for (;;) Line 4803  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
             GETCHARLEN(c, eptr, len);                {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
             prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
             if ((prop_chartype == prop_value) == prop_fail_result)              if ((prop_chartype == prop_value) == prop_fail_result)
               break;                break;
Line 3803  for (;;) Line 4820  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
             GETCHARLEN(c, eptr, len);                {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
             prop_script = UCD_SCRIPT(c);              prop_script = UCD_SCRIPT(c);
             if ((prop_script == prop_value) == prop_fail_result)              if ((prop_script == prop_value) == prop_fail_result)
               break;                break;
             eptr+= len;              eptr+= len;
             }              }
           break;            break;
   
             case PT_ALNUM:
             for (i = min; i < max; i++)
               {
               int len = 1;
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_L || prop_category == ucp_N)
                    == prop_fail_result)
                 break;
               eptr+= len;
               }
             break;
   
             case PT_SPACE:    /* Perl space */
             for (i = min; i < max; i++)
               {
               int len = 1;
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                    c == CHAR_FF || c == CHAR_CR)
                    == prop_fail_result)
                 break;
               eptr+= len;
               }
             break;
   
             case PT_PXSPACE:  /* POSIX space */
             for (i = min; i < max; i++)
               {
               int len = 1;
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
                    c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
                    == prop_fail_result)
                 break;
               eptr+= len;
               }
             break;
   
             case PT_WORD:
             for (i = min; i < max; i++)
               {
               int len = 1;
               if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               GETCHARLENTEST(c, eptr, len);
               prop_category = UCD_CATEGORY(c);
               if ((prop_category == ucp_L || prop_category == ucp_N ||
                    c == CHAR_UNDERSCORE) == prop_fail_result)
                 break;
               eptr+= len;
               }
             break;
   
             default:
             RRETURN(PCRE_ERROR_INTERNAL);
           }            }
   
         /* eptr is now past the end of the maximum run */          /* eptr is now past the end of the maximum run */
Line 3832  for (;;) Line 4930  for (;;)
         {          {
         for (i = min; i < max; i++)          for (i = min; i < max; i++)
           {            {
           if (eptr >= md->end_subject) break;            if (eptr >= md->end_subject)
               {
               SCHECK_PARTIAL();
               break;
               }
           GETCHARINCTEST(c, eptr);            GETCHARINCTEST(c, eptr);
           prop_category = UCD_CATEGORY(c);            prop_category = UCD_CATEGORY(c);
           if (prop_category == ucp_M) break;            if (prop_category == ucp_M) break;
Line 3852  for (;;) Line 4954  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;
   
         for(;;)          for(;;)
           {            {
           RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45);
Line 3887  for (;;) Line 4990  for (;;)
             {              {
             for (i = min; i < max; i++)              for (i = min; i < max; i++)
               {                {
               if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break;                if (eptr >= md->end_subject)
                   {
                   SCHECK_PARTIAL();
                   break;
                   }
                 if (IS_NEWLINE(eptr)) break;
               eptr++;                eptr++;
               while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;                while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
               }                }
Line 3899  for (;;) Line 5007  for (;;)
             {              {
             for (i = min; i < max; i++)              for (i = min; i < max; i++)
               {                {
               if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break;                if (eptr >= md->end_subject)
                   {
                   SCHECK_PARTIAL();
                   break;
                   }
                 if (IS_NEWLINE(eptr)) break;
               eptr++;                eptr++;
               while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;                while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
               }                }
Line 3911  for (;;) Line 5024  for (;;)
             {              {
             for (i = min; i < max; i++)              for (i = min; i < max; i++)
               {                {
               if (eptr >= md->end_subject) break;                if (eptr >= md->end_subject)
                   {
                   SCHECK_PARTIAL();
                   break;
                   }
               eptr++;                eptr++;
               while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;                while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
               }                }
Line 3924  for (;;) Line 5041  for (;;)
           case OP_ANYBYTE:            case OP_ANYBYTE:
           c = max - min;            c = max - min;
           if (c > (unsigned int)(md->end_subject - eptr))            if (c > (unsigned int)(md->end_subject - eptr))
             c = md->end_subject - eptr;              {
           eptr += c;              eptr = md->end_subject;
               SCHECK_PARTIAL();
               }
             else eptr += c;
           break;            break;
   
           case OP_ANYNL:            case OP_ANYNL:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c == 0x000d)              if (c == 0x000d)
               {                {
Line 3957  for (;;) Line 5081  for (;;)
             {              {
             BOOL gotspace;              BOOL gotspace;
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             switch(c)              switch(c)
               {                {
Line 3995  for (;;) Line 5123  for (;;)
             {              {
             BOOL gotspace;              BOOL gotspace;
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             switch(c)              switch(c)
               {                {
Line 4019  for (;;) Line 5151  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;              if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;
             eptr+= len;              eptr+= len;
Line 4030  for (;;) Line 5166  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;              if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;
             eptr+= len;              eptr+= len;
Line 4041  for (;;) Line 5181  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;              if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;
             eptr+= len;              eptr+= len;
Line 4052  for (;;) Line 5196  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;              if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;
             eptr+= len;              eptr+= len;
Line 4063  for (;;) Line 5211  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;              if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;
             eptr+= len;              eptr+= len;
Line 4074  for (;;) Line 5226  for (;;)
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             int len = 1;              int len = 1;
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             GETCHARLEN(c, eptr, len);              GETCHARLEN(c, eptr, len);
             if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;              if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
             eptr+= len;              eptr+= len;
Line 4106  for (;;) Line 5262  for (;;)
           case OP_ANY:            case OP_ANY:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
               if (IS_NEWLINE(eptr)) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4115  for (;;) Line 5276  for (;;)
           case OP_ANYBYTE:            case OP_ANYBYTE:
           c = max - min;            c = max - min;
           if (c > (unsigned int)(md->end_subject - eptr))            if (c > (unsigned int)(md->end_subject - eptr))
             c = md->end_subject - eptr;              {
           eptr += c;              eptr = md->end_subject;
               SCHECK_PARTIAL();
               }
             else eptr += c;
           break;            break;
   
           case OP_ANYNL:            case OP_ANYNL:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             c = *eptr;              c = *eptr;
             if (c == 0x000d)              if (c == 0x000d)
               {                {
Line 4143  for (;;) Line 5311  for (;;)
           case OP_NOT_HSPACE:            case OP_NOT_HSPACE:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             c = *eptr;              c = *eptr;
             if (c == 0x09 || c == 0x20 || c == 0xa0) break;              if (c == 0x09 || c == 0x20 || c == 0xa0) break;
             eptr++;              eptr++;
Line 4153  for (;;) Line 5325  for (;;)
           case OP_HSPACE:            case OP_HSPACE:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             c = *eptr;              c = *eptr;
             if (c != 0x09 && c != 0x20 && c != 0xa0) break;              if (c != 0x09 && c != 0x20 && c != 0xa0) break;
             eptr++;              eptr++;
Line 4163  for (;;) Line 5339  for (;;)
           case OP_NOT_VSPACE:            case OP_NOT_VSPACE:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             c = *eptr;              c = *eptr;
             if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85)              if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85)
               break;                break;
Line 4174  for (;;) Line 5354  for (;;)
           case OP_VSPACE:            case OP_VSPACE:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject) break;              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
                 break;
                 }
             c = *eptr;              c = *eptr;
             if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85)              if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85)
               break;                break;
Line 4185  for (;;) Line 5369  for (;;)
           case OP_NOT_DIGIT:            case OP_NOT_DIGIT:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
               break;                break;
                 }
               if ((md->ctypes[*eptr] & ctype_digit) != 0) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4194  for (;;) Line 5382  for (;;)
           case OP_DIGIT:            case OP_DIGIT:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
               break;                break;
                 }
               if ((md->ctypes[*eptr] & ctype_digit) == 0) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4203  for (;;) Line 5395  for (;;)
           case OP_NOT_WHITESPACE:            case OP_NOT_WHITESPACE:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
               break;                break;
                 }
               if ((md->ctypes[*eptr] & ctype_space) != 0) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4212  for (;;) Line 5408  for (;;)
           case OP_WHITESPACE:            case OP_WHITESPACE:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
               break;                break;
                 }
               if ((md->ctypes[*eptr] & ctype_space) == 0) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4221  for (;;) Line 5421  for (;;)
           case OP_NOT_WORDCHAR:            case OP_NOT_WORDCHAR:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
               break;                break;
                 }
               if ((md->ctypes[*eptr] & ctype_word) != 0) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4230  for (;;) Line 5434  for (;;)
           case OP_WORDCHAR:            case OP_WORDCHAR:
           for (i = min; i < max; i++)            for (i = min; i < max; i++)
             {              {
             if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)              if (eptr >= md->end_subject)
                 {
                 SCHECK_PARTIAL();
               break;                break;
                 }
               if ((md->ctypes[*eptr] & ctype_word) == 0) break;
             eptr++;              eptr++;
             }              }
           break;            break;
Line 4253  for (;;) Line 5461  for (;;)
   
       /* Get here if we can't make it match with any permitted repetitions */        /* Get here if we can't make it match with any permitted repetitions */
   
       RRETURN(MATCH_NOMATCH);        MRRETURN(MATCH_NOMATCH);
       }        }
     /* Control never gets here */      /* Control never gets here */
   
Line 4286  switch (frame->Xwhere) Line 5494  switch (frame->Xwhere)
   LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)    LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)
   LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)    LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)
   LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)    LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)
   LBL(53) LBL(54)    LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58)
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
   LBL(16) LBL(18) LBL(20) LBL(21) LBL(22) LBL(23) LBL(28) LBL(30)    LBL(16) LBL(18) LBL(20) LBL(21) 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)
 #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
 #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF8 */
   default:    default:
Line 4409  const uschar *tables; Line 5618  const uschar *tables;
 const uschar *start_bits = NULL;  const uschar *start_bits = NULL;
 USPTR start_match = (USPTR)subject + start_offset;  USPTR start_match = (USPTR)subject + start_offset;
 USPTR end_subject;  USPTR end_subject;
   USPTR start_partial = NULL;
 USPTR req_byte_ptr = start_match - 1;  USPTR req_byte_ptr = start_match - 1;
   
 pcre_study_data internal_study;  pcre_study_data internal_study;
Line 4424  if ((options & ~PUBLIC_EXEC_OPTIONS) != Line 5634  if ((options & ~PUBLIC_EXEC_OPTIONS) !=
 if (re == NULL || subject == NULL ||  if (re == NULL || subject == NULL ||
    (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;     (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
 if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;  if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
   if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
   
   /* This information is for finding all the numbers associated with a given
   name, for condition testing. */
   
   md->name_table = (uschar *)re + re->name_table_offset;
   md->name_count = re->name_count;
   md->name_entry_size = re->name_entry_size;
   
 /* Fish out the optional data from the extra_data structure, first setting  /* Fish out the optional data from the extra_data structure, first setting
 the default values. */  the default values. */
Line 4487  end_subject = md->end_subject; Line 5705  end_subject = md->end_subject;
   
 md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;  md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
 utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0;  utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0;
   md->use_ucp = (re->options & PCRE_UCP) != 0;
 md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;  md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
   
 md->notbol = (options & PCRE_NOTBOL) != 0;  md->notbol = (options & PCRE_NOTBOL) != 0;
 md->noteol = (options & PCRE_NOTEOL) != 0;  md->noteol = (options & PCRE_NOTEOL) != 0;
 md->notempty = (options & PCRE_NOTEMPTY) != 0;  md->notempty = (options & PCRE_NOTEMPTY) != 0;
 md->partial = (options & PCRE_PARTIAL) != 0;  md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
   md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 :
                 ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0;
 md->hitend = FALSE;  md->hitend = FALSE;
   md->mark = NULL;                        /* In case never set */
   
 md->recursive = NULL;                   /* No recursion at top level */  md->recursive = NULL;                   /* No recursion at top level */
   
Line 4533  switch ((((options & PCRE_NEWLINE_BITS) Line 5755  switch ((((options & PCRE_NEWLINE_BITS)
         (pcre_uint32)options) & PCRE_NEWLINE_BITS)          (pcre_uint32)options) & PCRE_NEWLINE_BITS)
   {    {
   case 0: newline = NEWLINE; break;   /* Compile-time default */    case 0: newline = NEWLINE; break;   /* Compile-time default */
   case PCRE_NEWLINE_CR: newline = '\r'; break;    case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
   case PCRE_NEWLINE_LF: newline = '\n'; break;    case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
   case PCRE_NEWLINE_CR+    case PCRE_NEWLINE_CR+
        PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;         PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
   case PCRE_NEWLINE_ANY: newline = -1; break;    case PCRE_NEWLINE_ANY: newline = -1; break;
   case PCRE_NEWLINE_ANYCRLF: newline = -2; break;    case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
   default: return PCRE_ERROR_BADNEWLINE;    default: return PCRE_ERROR_BADNEWLINE;
Line 4566  else Line 5788  else
     }      }
   }    }
   
 /* Partial matching is supported only for a restricted set of regexes at the  /* Partial matching was originally supported only for a restricted set of
 moment. */  regexes; from release 8.00 there are no restrictions, but the bits are still
   defined (though never set). So there's no harm in leaving this code. */
   
 if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)  if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)
   return PCRE_ERROR_BADPARTIAL;    return PCRE_ERROR_BADPARTIAL;
Line 4578  back the character offset. */ Line 5801  back the character offset. */
 #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
 if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
   {    {
   if (_pcre_valid_utf8((uschar *)subject, length) >= 0)    int tb;
     return PCRE_ERROR_BADUTF8;    if ((tb = _pcre_valid_utf8((USPTR)subject, length)) >= 0)
       return (tb == length && md->partial > 1)?
         PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
   if (start_offset > 0 && start_offset < length)    if (start_offset > 0 && start_offset < length)
     {      {
     int tb = ((uschar *)subject)[start_offset];      tb = ((USPTR)subject)[start_offset] & 0xc0;
     if (tb > 127)      if (tb == 0x80) return PCRE_ERROR_BADUTF8_OFFSET;
       {  
       tb &= 0xc0;  
       if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET;  
       }  
     }      }
   }    }
 #endif  #endif
Line 4654  if (!anchored) Line 5875  if (!anchored)
     }      }
   else    else
     if (!startline && study != NULL &&      if (!startline && study != NULL &&
       (study->options & PCRE_STUDY_MAPPED) != 0)        (study->flags & PCRE_STUDY_MAPPED) != 0)
         start_bits = study->start_bits;          start_bits = study->start_bits;
   }    }
   
Line 4688  for(;;) Line 5909  for(;;)
     while (iptr < iend) *iptr++ = -1;      while (iptr < iend) *iptr++ = -1;
     }      }
   
   /* Advance to a unique first char if possible. If firstline is TRUE, the    /* If firstline is TRUE, the start of the match is constrained to the first
   start of the match is constrained to the first line of a multiline string.    line of a multiline string. That is, the match must be before or at the first
   That is, the match must be before or at the first newline. Implement this by    newline. Implement this by temporarily adjusting end_subject so that we stop
   temporarily adjusting end_subject so that we stop scanning at a newline. If    scanning at a newline. If the match fails at the newline, later code breaks
   the match fails at the newline, later code breaks this loop. */    this loop. */
   
   if (firstline)    if (firstline)
     {      {
Line 4712  for(;;) Line 5933  for(;;)
     end_subject = t;      end_subject = t;
     }      }
   
   /* Now advance to a unique first byte if there is one. */    /* There are some optimizations that avoid running the match if a known
     starting point is not found, or if a known later character is not present.
     However, there is an option that disables these, for testing and for ensuring
     that all callouts do actually occur. The option can be set in the regex by
     (*NO_START_OPT) or passed in match-time options. */
   
   if (first_byte >= 0)    if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
     {      {
     if (first_byte_caseless)      /* Advance to a unique first byte if there is one. */
       while (start_match < end_subject && md->lcc[*start_match] != first_byte)  
         start_match++;  
     else  
       while (start_match < end_subject && *start_match != first_byte)  
         start_match++;  
     }  
   
   /* Or to just after a linebreak for a multiline match */      if (first_byte >= 0)
         {
         if (first_byte_caseless)
           while (start_match < end_subject && md->lcc[*start_match] != first_byte)
             start_match++;
         else
           while (start_match < end_subject && *start_match != first_byte)
             start_match++;
         }
   
   else if (startline)      /* Or to just after a linebreak for a multiline match */
     {  
     if (start_match > md->start_subject + start_offset)      else if (startline)
       {        {
 #ifdef SUPPORT_UTF8        if (start_match > md->start_subject + start_offset)
       if (utf8)  
         {          {
         while (start_match < end_subject && !WAS_NEWLINE(start_match))  #ifdef SUPPORT_UTF8
           if (utf8)
           {            {
           start_match++;            while (start_match < end_subject && !WAS_NEWLINE(start_match))
           while(start_match < end_subject && (*start_match & 0xc0) == 0x80)              {
             start_match++;              start_match++;
               while(start_match < end_subject && (*start_match & 0xc0) == 0x80)
                 start_match++;
               }
           }            }
         }          else
       else  
 #endif  #endif
       while (start_match < end_subject && !WAS_NEWLINE(start_match))          while (start_match < end_subject && !WAS_NEWLINE(start_match))
         start_match++;            start_match++;
   
       /* If we have just passed a CR and the newline option is ANY or ANYCRLF,          /* If we have just passed a CR and the newline option is ANY or ANYCRLF,
       and we are now at a LF, advance the match position by one more character.          and we are now at a LF, advance the match position by one more character.
       */          */
   
       if (start_match[-1] == '\r' &&          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 == '\n')               *start_match == CHAR_NL)
         start_match++;            start_match++;
           }
       }        }
     }  
   
   /* Or to a non-unique first byte after study */      /* Or to a non-unique first byte after study */
   
   else if (start_bits != NULL)      else if (start_bits != NULL)
     {  
     while (start_match < end_subject)  
       {        {
       register unsigned int c = *start_match;        while (start_match < end_subject)
       if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++;          {
           register unsigned int c = *start_match;
           if ((start_bits[c/8] & (1 << (c&7))) == 0)
             {
             start_match++;
   #ifdef SUPPORT_UTF8
             if (utf8)
               while(start_match < end_subject && (*start_match & 0xc0) == 0x80)
                 start_match++;
   #endif
             }
         else break;          else break;
           }
       }        }
     }      }   /* Starting optimizations */
   
   /* Restore fudged end_subject */    /* Restore fudged end_subject */
   
   end_subject = save_end_subject;    end_subject = save_end_subject;
   
 #ifdef DEBUG  /* Sigh. Some compilers never learn. */    /* The following two optimizations are disabled for partial matching or if
   printf(">>>> Match against: ");    disabling is explicitly requested. */
   pchars(start_match, end_subject - start_match, TRUE, md);  
   printf("\n");  
 #endif  
   
   /* If req_byte is set, we know that that character must appear in the subject    if ((options & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial)
   for the match to succeed. If the first character is set, req_byte must be  
   later in the subject; otherwise the test starts at the match point. This  
   optimization can save a huge amount of backtracking in patterns with nested  
   unlimited repeats that aren't going to match. Writing separate code for  
   cased/caseless versions makes it go faster, as does using an autoincrement  
   and backing off on a match.  
   
   HOWEVER: when the subject string is very, very long, searching to its end can  
   take a long time, and give bad performance on quite ordinary patterns. This  
   showed up when somebody was matching something like /^\d+C/ on a 32-megabyte  
   string... so we don't do this when the string is sufficiently long.  
   
   ALSO: this processing is disabled when partial matching is requested.  
   */  
   
   if (req_byte >= 0 &&  
       end_subject - start_match < REQ_BYTE_MAX &&  
       !md->partial)  
     {      {
     register USPTR p = start_match + ((first_byte >= 0)? 1 : 0);      /* If the pattern was studied, a minimum subject length may be set. This is
       a lower bound; no actual string of that length may actually match the
       pattern. Although the value is, strictly, in characters, we treat it as
       bytes to avoid spending too much time in this optimization. */
   
       if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
           (pcre_uint32)(end_subject - start_match) < study->minlength)
         {
         rc = MATCH_NOMATCH;
         break;
         }
   
       /* If req_byte is set, we know that that character must appear in the
       subject for the match to succeed. If the first character is set, req_byte
       must be later in the subject; otherwise the test starts at the match point.
       This optimization can save a huge amount of backtracking in patterns with
       nested unlimited repeats that aren't going to match. Writing separate code
       for cased/caseless versions makes it go faster, as does using an
       autoincrement and backing off on a match.
   
     /* We don't need to repeat the search if we haven't yet reached the      HOWEVER: when the subject string is very, very long, searching to its end
     place we found it at last time. */      can take a long time, and give bad performance on quite ordinary patterns.
       This showed up when somebody was matching something like /^\d+C/ on a
       32-megabyte string... so we don't do this when the string is sufficiently
       long. */
   
     if (p > req_byte_ptr)      if (req_byte >= 0 && end_subject - start_match < REQ_BYTE_MAX)
       {        {
       if (req_byte_caseless)        register USPTR p = start_match + ((first_byte >= 0)? 1 : 0);
   
         /* We don't need to repeat the search if we haven't yet reached the
         place we found it at last time. */
   
         if (p > req_byte_ptr)
         {          {
         while (p < end_subject)          if (req_byte_caseless)
           {            {
           register int pp = *p++;            while (p < end_subject)
           if (pp == req_byte || pp == req_byte2) { p--; break; }              {
               register int pp = *p++;
               if (pp == req_byte || pp == req_byte2) { p--; break; }
               }
           }            }
         }          else
       else  
         {  
         while (p < end_subject)  
           {            {
           if (*p++ == req_byte) { p--; break; }            while (p < end_subject)
               {
               if (*p++ == req_byte) { p--; break; }
               }
           }            }
         }  
   
       /* If we can't find the required character, break the matching loop,          /* If we can't find the required character, break the matching loop,
       forcing a match failure. */          forcing a match failure. */
   
       if (p >= end_subject)          if (p >= end_subject)
         {            {
         rc = MATCH_NOMATCH;            rc = MATCH_NOMATCH;
         break;            break;
         }            }
   
       /* If we have found the required character, save the point where we          /* If we have found the required character, save the point where we
       found it, so that we don't search again next time round the loop if          found it, so that we don't search again next time round the loop if
       the start hasn't passed this character yet. */          the start hasn't passed this character yet. */
   
       req_byte_ptr = p;          req_byte_ptr = p;
           }
       }        }
     }      }
   
   /* OK, we can now run the match. */  #ifdef PCRE_DEBUG  /* Sigh. Some compilers never learn. */
     printf(">>>> Match against: ");
     pchars(start_match, end_subject - start_match, TRUE, md);
     printf("\n");
   #endif
   
     /* OK, we can now run the match. If "hitend" is set afterwards, remember the
     first starting point for which a partial match was found. */
   
   md->start_match_ptr = start_match;    md->start_match_ptr = start_match;
     md->start_used_ptr = start_match;
   md->match_call_count = 0;    md->match_call_count = 0;
   rc = match(start_match, md->start_code, start_match, 2, md, ims, NULL, 0, 0);    rc = match(start_match, md->start_code, start_match, NULL, 2, md, ims, NULL,
       0, 0);
     if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr;
   
   switch(rc)    switch(rc)
     {      {
       /* SKIP passes back the next starting point explicitly, but if it is the
       same as the match we have just done, treat it as NOMATCH. */
   
       case MATCH_SKIP:
       if (md->start_match_ptr != start_match)
         {
         new_start_match = md->start_match_ptr;
         break;
         }
       /* Fall through */
   
       /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched
       the SKIP's arg was not found. We also treat this as NOMATCH. */
   
       case MATCH_SKIP_ARG:
       /* Fall through */
   
     /* NOMATCH and PRUNE advance by one character. THEN at this level acts      /* NOMATCH and PRUNE advance by one character. THEN at this level acts
     exactly like PRUNE. */      exactly like PRUNE. */
   
Line 4861  for(;;) Line 6134  for(;;)
 #endif  #endif
     break;      break;
   
     /* SKIP passes back the next starting point explicitly. */  
   
     case MATCH_SKIP:  
     new_start_match = md->start_match_ptr;  
     break;  
   
     /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */      /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */
   
     case MATCH_COMMIT:      case MATCH_COMMIT:
     rc = MATCH_NOMATCH;      rc = MATCH_NOMATCH;
     goto ENDLOOP;      goto ENDLOOP;
   
     /* Any other return is some kind of error. */      /* Any other return is either a match, or some kind of error. */
   
     default:      default:
     goto ENDLOOP;      goto ENDLOOP;
Line 4903  for(;;) Line 6170  for(;;)
   not contain any explicit matches for \r or \n, and the newline option is CRLF    not contain any explicit matches for \r or \n, and the newline option is CRLF
   or ANY or ANYCRLF, advance the match position by one more character. */    or ANY or ANYCRLF, advance the match position by one more character. */
   
   if (start_match[-1] == '\r' &&    if (start_match[-1] == CHAR_CR &&
       start_match < end_subject &&        start_match < end_subject &&
       *start_match == '\n' &&        *start_match == CHAR_NL &&
       (re->flags & PCRE_HASCRORLF) == 0 &&        (re->flags & PCRE_HASCRORLF) == 0 &&
         (md->nltype == NLTYPE_ANY ||          (md->nltype == NLTYPE_ANY ||
          md->nltype == NLTYPE_ANYCRLF ||           md->nltype == NLTYPE_ANYCRLF ||
          md->nllen == 2))           md->nllen == 2))
     start_match++;      start_match++;
   
   }   /* End of for(;;) "bumpalong" loop */    md->mark = NULL;   /* Reset for start of next match attempt */
     }                  /* End of for(;;) "bumpalong" loop */
   
 /* ==========================================================================*/  /* ==========================================================================*/
   
Line 4936  capturing parentheses than vector slots. Line 6204  capturing parentheses than vector slots.
   
 ENDLOOP:  ENDLOOP:
   
 if (rc == MATCH_MATCH)  if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
   {    {
   if (using_temporary_offsets)    if (using_temporary_offsets)
     {      {
Line 4962  if (rc == MATCH_MATCH) Line 6230  if (rc == MATCH_MATCH)
   
   if (offsetcount < 2) rc = 0; else    if (offsetcount < 2) rc = 0; else
     {      {
     offsets[0] = md->start_match_ptr - md->start_subject;      offsets[0] = (int)(md->start_match_ptr - md->start_subject);
     offsets[1] = md->end_match_ptr - md->start_subject;      offsets[1] = (int)(md->end_match_ptr - md->start_subject);
     }      }
   
   DPRINTF((">>>> returning %d\n", rc));    DPRINTF((">>>> returning %d\n", rc));
   return rc;    goto RETURN_MARK;
   }    }
   
 /* Control gets here if there has been an error, or if the overall match  /* Control gets here if there has been an error, or if the overall match
Line 4979  if (using_temporary_offsets) Line 6247  if (using_temporary_offsets)
   (pcre_free)(md->offset_vector);    (pcre_free)(md->offset_vector);
   }    }
   
 if (rc != MATCH_NOMATCH)  /* For anything other than nomatch or partial match, just return the code. */
   
   if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
   {    {
   DPRINTF((">>>> error: returning %d\n", rc));    DPRINTF((">>>> error: returning %d\n", rc));
   return rc;    return rc;
   }    }
 else if (md->partial && md->hitend)  
   /* Handle partial matches - disable any mark data */
   
   if (start_partial != NULL)
   {    {
   DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));    DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
   return PCRE_ERROR_PARTIAL;    md->mark = NULL;
     if (offsetcount > 1)
       {
       offsets[0] = (int)(start_partial - (USPTR)subject);
       offsets[1] = (int)(end_subject - (USPTR)subject);
       }
     rc = PCRE_ERROR_PARTIAL;
   }    }
   
   /* This is the classic nomatch case */
   
 else  else
   {    {
   DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));    DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
   return PCRE_ERROR_NOMATCH;    rc = PCRE_ERROR_NOMATCH;
   }    }
   
   /* Return the MARK data if it has been requested. */
   
   RETURN_MARK:
   
   if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
     *(extra_data->mark) = (unsigned char *)(md->mark);
   return rc;
 }  }
   
 /* End of pcre_exec.c */  /* End of pcre_exec.c */

Removed from v.1.2  
changed lines
  Added in v.1.5


E-mail: