# Diff of /code/trunk/pcre_dfa_exec.c

revision 645 by ph10, Sun Jul 31 17:02:18 2011 UTC revision 1100 by chpe, Tue Oct 16 15:56:26 2012 UTC
# Line 7  and semantics are as close as possible t Line 7  and semantics are as close as possible t
7  below for why this module is different).  below for why this module is different).
8
9                         Written by Philip Hazel                         Written by Philip Hazel
10             Copyright (c) 1997-2011 University of Cambridge             Copyright (c) 1997-2012 University of Cambridge
11
12  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
13  Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
# Line 38  POSSIBILITY OF SUCH DAMAGE. Line 38  POSSIBILITY OF SUCH DAMAGE.
38  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
39  */  */
40

41  /* This module contains the external function pcre_dfa_exec(), which is an  /* This module contains the external function pcre_dfa_exec(), which is an
42  alternative matching function that uses a sort of DFA algorithm (not a true  alternative matching function that uses a sort of DFA algorithm (not a true
43  FSM). This is NOT Perl- compatible, but it has advantages in certain  FSM). This is NOT Perl-compatible, but it has advantages in certain
44  applications. */  applications. */
45
46
# Line 113  small value. Non-zero values in the tabl Line 112  small value. Non-zero values in the tabl
112  the character is to be found. ***NOTE*** If the start of this table is  the character is to be found. ***NOTE*** If the start of this table is
113  modified, the three tables that follow must also be modified. */  modified, the three tables that follow must also be modified. */
114
115  static const uschar coptable[] = {  static const pcre_uint8 coptable[] = {
116    0,                             /* End                                    */    0,                             /* End                                    */
117    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
118    0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */    0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */
# Line 128  static const uschar coptable[] = { Line 127  static const uschar coptable[] = {
127    1,                             /* noti                                   */    1,                             /* noti                                   */
128    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
129    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
130    3, 3, 3,                       /* upto, minupto, exact                   */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto, minupto                          */
131    1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */    1+IMM2_SIZE,                   /* exact                                  */
132      1, 1, 1, 1+IMM2_SIZE,          /* *+, ++, ?+, upto+                      */
133    1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */    1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
134    3, 3, 3,                       /* upto I, minupto I, exact I             */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto I, minupto I                      */
135    1, 1, 1, 3,                    /* *+I, ++I, ?+I, upto+I                  */    1+IMM2_SIZE,                   /* exact I                                */
136      1, 1, 1, 1+IMM2_SIZE,          /* *+I, ++I, ?+I, upto+I                  */
137    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
138    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
139    3, 3, 3,                       /* NOT upto, minupto, exact               */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto, minupto                      */
140    1, 1, 1, 3,                    /* NOT *+, ++, ?+, upto+                  */    1+IMM2_SIZE,                   /* NOT exact                              */
141      1, 1, 1, 1+IMM2_SIZE,          /* NOT *+, ++, ?+, upto+                  */
142    1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */    1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
143    3, 3, 3,                       /* NOT upto I, minupto I, exact I         */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto I, minupto I                  */
144    1, 1, 1, 3,                    /* NOT *+I, ++I, ?+I, upto+I              */    1+IMM2_SIZE,                   /* NOT exact I                            */
145      1, 1, 1, 1+IMM2_SIZE,          /* NOT *+I, ++I, ?+I, upto+I              */
146    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
147    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
148    3, 3, 3,                       /* Type upto, minupto, exact              */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* Type upto, minupto                     */
149    1, 1, 1, 3,                    /* Type *+, ++, ?+, upto+                 */    1+IMM2_SIZE,                   /* Type exact                             */
150      1, 1, 1, 1+IMM2_SIZE,          /* Type *+, ++, ?+, upto+                 */
151    /* Character class & ref repeats                                         */    /* Character class & ref repeats                                         */
152    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */
153    0, 0,                          /* CRRANGE, CRMINRANGE                    */    0, 0,                          /* CRRANGE, CRMINRANGE                    */
# Line 164  static const uschar coptable[] = { Line 168  static const uschar coptable[] = {
168    0,                             /* Assert not                             */    0,                             /* Assert not                             */
169    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
170    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
171    0, 0, 0, 0, 0, 0,              /* ONCE, BRA, BRAPOS, CBRA, CBRAPOS, COND */    0, 0,                          /* ONCE, ONCE_NC                          */
172      0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
173    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
174    0, 0,                          /* CREF, NCREF                            */    0, 0,                          /* CREF, NCREF                            */
175    0, 0,                          /* RREF, NRREF                            */    0, 0,                          /* RREF, NRREF                            */
# Line 181  remember the fact that a character could Line 186  remember the fact that a character could
186  the subject is reached. ***NOTE*** If the start of this table is modified, the  the subject is reached. ***NOTE*** If the start of this table is modified, the
187  two tables that follow must also be modified. */  two tables that follow must also be modified. */
188
189  static const uschar poptable[] = {  static const pcre_uint8 poptable[] = {
190    0,                             /* End                                    */    0,                             /* End                                    */
191    0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */    0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */
192    1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */    1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */
# Line 232  static const uschar poptable[] = { Line 237  static const uschar poptable[] = {
237    0,                             /* Assert not                             */    0,                             /* Assert not                             */
238    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
239    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
240    0, 0, 0, 0, 0, 0,              /* ONCE, BRA, BRAPOS, CBRA, CBRAPOS, COND */    0, 0,                          /* ONCE, ONCE_NC                          */
241      0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
242    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
243    0, 0,                          /* CREF, NCREF                            */    0, 0,                          /* CREF, NCREF                            */
244    0, 0,                          /* RREF, NRREF                            */    0, 0,                          /* RREF, NRREF                            */
# Line 247  static const uschar poptable[] = { Line 253  static const uschar poptable[] = {
253  /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,  /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
254  and \w */  and \w */
255
256  static const uschar toptable1[] = {  static const pcre_uint8 toptable1[] = {
257    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
258    ctype_digit, ctype_digit,    ctype_digit, ctype_digit,
259    ctype_space, ctype_space,    ctype_space, ctype_space,
# Line 255  static const uschar toptable1[] = { Line 261  static const uschar toptable1[] = {
261    0, 0                            /* OP_ANY, OP_ALLANY */    0, 0                            /* OP_ANY, OP_ALLANY */
262  };  };
263
264  static const uschar toptable2[] = {  static const pcre_uint8 toptable2[] = {
265    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
266    ctype_digit, 0,    ctype_digit, 0,
267    ctype_space, 0,    ctype_space, 0,
# Line 275  typedef struct stateblock { Line 281  typedef struct stateblock {
281    int data;                       /* Some use extra data */    int data;                       /* Some use extra data */
282  } stateblock;  } stateblock;
283
284  #define INTS_PER_STATEBLOCK  (sizeof(stateblock)/sizeof(int))  #define INTS_PER_STATEBLOCK  (int)(sizeof(stateblock)/sizeof(int))
285
286
287  #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
# Line 294  Returns:       nothing Line 300  Returns:       nothing
300  */  */
301
302  static void  static void
303  pchars(unsigned char *p, int length, FILE *f)  pchars(const pcre_uchar *p, int length, FILE *f)
304  {  {
305  int c;  pcre_uint32 c;
306  while (length-- > 0)  while (length-- > 0)
307    {    {
308    if (isprint(c = *(p++)))    if (isprint(c = *(p++)))
309      fprintf(f, "%c", c);      fprintf(f, "%c", c);
310    else    else
311      fprintf(f, "\\x%02x", c);      fprintf(f, "\\x{%02x}", c);
312    }    }
313  }  }
314  #endif  #endif
# Line 375  for the current character, one for the f Line 381  for the current character, one for the f
381      next_new_state->count  = (y); \      next_new_state->count  = (y); \
382      next_new_state->data   = (z); \      next_new_state->data   = (z); \
383      next_new_state++; \      next_new_state++; \
384      DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \      DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \
385          (x), (y), (z), __LINE__)); \
386      } \      } \
387    else return PCRE_ERROR_DFA_WSSIZE    else return PCRE_ERROR_DFA_WSSIZE
388
# Line 384  for the current character, one for the f Line 391  for the current character, one for the f
391  static int  static int
392  internal_dfa_exec(  internal_dfa_exec(
393    dfa_match_data *md,    dfa_match_data *md,
394    const uschar *this_start_code,    const pcre_uchar *this_start_code,
395    const uschar *current_subject,    const pcre_uchar *current_subject,
396    int start_offset,    int start_offset,
397    int *offsets,    int *offsets,
398    int offsetcount,    int offsetcount,
# Line 396  internal_dfa_exec( Line 403  internal_dfa_exec(
403  stateblock *active_states, *new_states, *temp_states;  stateblock *active_states, *new_states, *temp_states;
404  stateblock *next_active_state, *next_new_state;  stateblock *next_active_state, *next_new_state;
405
406  const uschar *ctypes, *lcc, *fcc;  const pcre_uint8 *ctypes, *lcc, *fcc;
407  const uschar *ptr;  const pcre_uchar *ptr;
408  const uschar *end_code, *first_op;  const pcre_uchar *end_code, *first_op;
409
410  dfa_recursion_info new_recursive;  dfa_recursion_info new_recursive;
411
# Line 407  int active_count, new_count, match_count Line 414  int active_count, new_count, match_count
414  /* Some fields in the md block are frequently referenced, so we load them into  /* Some fields in the md block are frequently referenced, so we load them into
415  independent variables in the hope that this will perform better. */  independent variables in the hope that this will perform better. */
416
417  const uschar *start_subject = md->start_subject;  const pcre_uchar *start_subject = md->start_subject;
418  const uschar *end_subject = md->end_subject;  const pcre_uchar *end_subject = md->end_subject;
419  const uschar *start_code = md->start_code;  const pcre_uchar *start_code = md->start_code;
420
421  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
422  BOOL utf8 = (md->poptions & PCRE_UTF8) != 0;  BOOL utf = (md->poptions & PCRE_UTF8) != 0;
423  #else  #else
424  BOOL utf8 = FALSE;  BOOL utf = FALSE;
425  #endif  #endif
426
427    BOOL reset_could_continue = FALSE;
428
429  rlevel++;  rlevel++;
430  offsetcount &= (-2);  offsetcount &= (-2);
431
# Line 440  new_count = 0; Line 449  new_count = 0;
449
450  first_op = this_start_code + 1 + LINK_SIZE +  first_op = this_start_code + 1 + LINK_SIZE +
451    ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||    ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
452      *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)? 2:0);      *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
453        ? IMM2_SIZE:0);
454
455  /* The first thing in any (sub) pattern is a bracket of some sort. Push all  /* The first thing in any (sub) pattern is a bracket of some sort. Push all
456  the alternative states onto the list, and find out where the end is. This  the alternative states onto the list, and find out where the end is. This
# Line 468  if (*first_op == OP_REVERSE) Line 478  if (*first_op == OP_REVERSE)
478    /* If we can't go back the amount required for the longest lookbehind    /* If we can't go back the amount required for the longest lookbehind
479    pattern, go back as far as we can; some alternatives may still be viable. */    pattern, go back as far as we can; some alternatives may still be viable. */
480
481  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
482    /* In character mode we have to step back character by character */    /* In character mode we have to step back character by character */
483
484    if (utf8)    if (utf)
485      {      {
486      for (gone_back = 0; gone_back < max_back; gone_back++)      for (gone_back = 0; gone_back < max_back; gone_back++)
487        {        {
488        if (current_subject <= start_subject) break;        if (current_subject <= start_subject) break;
489        current_subject--;        current_subject--;
490        while (current_subject > start_subject &&        ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--);
(*current_subject & 0xc0) == 0x80)
current_subject--;
491        }        }
492      }      }
493    else    else
# Line 540  else Line 548  else
548      {      {
549      int length = 1 + LINK_SIZE +      int length = 1 + LINK_SIZE +
550        ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||        ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
551          *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)?          *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
552          2:0);          ? IMM2_SIZE:0);
553      do      do
554        {        {
555        ADD_NEW((int)(end_code - start_code + length), 0);        ADD_NEW((int)(end_code - start_code + length), 0);
# Line 554  else Line 562  else
562
563  workspace[0] = 0;    /* Bit indicating which vector is current */  workspace[0] = 0;    /* Bit indicating which vector is current */
564
565  DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, end_code - start_code));  DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code)));
566
567  /* Loop for scanning the subject */  /* Loop for scanning the subject */
568
# Line 563  for (;;) Line 571  for (;;)
571    {    {
572    int i, j;    int i, j;
573    int clen, dlen;    int clen, dlen;
574    unsigned int c, d;    pcre_uint32 c, d;
575    int forced_fail = 0;    int forced_fail = 0;
576    BOOL could_continue = FALSE;    BOOL partial_newline = FALSE;
577      BOOL could_continue = reset_could_continue;
578      reset_could_continue = FALSE;
579
580    /* Make the new state list into the active state list and empty the    /* Make the new state list into the active state list and empty the
581    new state list. */    new state list. */
# Line 581  for (;;) Line 591  for (;;)
591
592  #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
593    printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);    printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);
594    pchars((uschar *)ptr, strlen((char *)ptr), stdout);    pchars(ptr, STRLEN_UC(ptr), stdout);
595    printf("\"\n");    printf("\"\n");
596
597    printf("%.*sActive states: ", rlevel*2-2, SP);    printf("%.*sActive states: ", rlevel*2-2, SP);
# Line 601  for (;;) Line 611  for (;;)
611
612    if (ptr < end_subject)    if (ptr < end_subject)
613      {      {
614      clen = 1;        /* Number of bytes in the character */      clen = 1;        /* Number of data items in the character */
615  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
616      if (utf8) { GETCHARLEN(c, ptr, clen); } else      GETCHARLENTEST(c, ptr, clen);
617  #endif  /* SUPPORT_UTF8 */  #else
618      c = *ptr;      c = *ptr;
619    #endif  /* SUPPORT_UTF */
620      }      }
621    else    else
622      {      {
# Line 621  for (;;) Line 632  for (;;)
632    for (i = 0; i < active_count; i++)    for (i = 0; i < active_count; i++)
633      {      {
634      stateblock *current_state = active_states + i;      stateblock *current_state = active_states + i;
635      BOOL caseless = FALSE;      BOOL caseless = FALSE;
636      const uschar *code;      const pcre_uchar *code;
637      int state_offset = current_state->offset;      int state_offset = current_state->offset;
638      int count, codevalue, rrc;      int count, codevalue, rrc;
639
# Line 635  for (;;) Line 646  for (;;)
646
647      /* A negative offset is a special case meaning "hold off going to this      /* A negative offset is a special case meaning "hold off going to this
648      (negated) state until the number of characters in the data field have      (negated) state until the number of characters in the data field have
649      been skipped". */      been skipped". If the could_continue flag was passed over from a previous
650        state, arrange for it to passed on. */
651
652      if (state_offset < 0)      if (state_offset < 0)
653        {        {
# Line 644  for (;;) Line 656  for (;;)
656          DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));          DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
658            current_state->data - 1);            current_state->data - 1);
659            if (could_continue) reset_could_continue = TRUE;
660          continue;          continue;
661          }          }
662        else        else
# Line 683  for (;;) Line 696  for (;;)
696      permitted.      permitted.
697
698      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
699      argument that is not a data character - but is always one byte long. We      argument that is not a data character - but is always one byte long because
700      have to take special action to deal with  \P, \p, \H, \h, \V, \v and \X in      the values are small. We have to take special action to deal with  \P, \p,
701      this case. To keep the other cases fast, convert these ones to new opcodes.      \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert
702      */      these ones to new opcodes. */
703
704      if (coptable[codevalue] > 0)      if (coptable[codevalue] > 0)
705        {        {
706        dlen = 1;        dlen = 1;
707  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
708        if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else        if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
709  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
710        d = code[coptable[codevalue]];        d = code[coptable[codevalue]];
711        if (codevalue >= OP_TYPESTAR)        if (codevalue >= OP_TYPESTAR)
712          {          {
# Line 738  for (;;) Line 751  for (;;)
751
752  /* ========================================================================== */  /* ========================================================================== */
753        /* Reached a closing bracket. If not at the end of the pattern, carry        /* Reached a closing bracket. If not at the end of the pattern, carry
754        on with the next opcode. For repeating opcodes, also add the repeat        on with the next opcode. For repeating opcodes, also add the repeat
755        state. Note that KETRPOS will always be encountered at the end of the        state. Note that KETRPOS will always be encountered at the end of the
756        subpattern, because the possessive subpattern repeats are always handled        subpattern, because the possessive subpattern repeats are always handled
757        using recursive calls. Thus, it never adds any new states.        using recursive calls. Thus, it never adds any new states.
758
759        At the end of the (sub)pattern, unless we have an empty string and        At the end of the (sub)pattern, unless we have an empty string and
760        PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the        PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the
761        start of the subject, save the match data, shifting up all previous        start of the subject, save the match data, shifting up all previous
# Line 751  for (;;) Line 764  for (;;)
764        case OP_KET:        case OP_KET:
765        case OP_KETRMIN:        case OP_KETRMIN:
766        case OP_KETRMAX:        case OP_KETRMAX:
767        case OP_KETRPOS:        case OP_KETRPOS:
768        if (code != end_code)        if (code != end_code)
769          {          {
# Line 768  for (;;) Line 781  for (;;)
781                  current_subject > start_subject + md->start_offset)))                  current_subject > start_subject + md->start_offset)))
782            {            {
783            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
784              else if (match_count > 0 && ++match_count * 2 >= offsetcount)              else if (match_count > 0 && ++match_count * 2 > offsetcount)
785                match_count = 0;                match_count = 0;
786            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
787            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
# Line 777  for (;;) Line 790  for (;;)
790              offsets[0] = (int)(current_subject - start_subject);              offsets[0] = (int)(current_subject - start_subject);
791              offsets[1] = (int)(ptr - start_subject);              offsets[1] = (int)(ptr - start_subject);
792              DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,              DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
793                offsets[1] - offsets[0], current_subject));                offsets[1] - offsets[0], (char *)current_subject));
794              }              }
795            if ((md->moptions & PCRE_DFA_SHORTEST) != 0)            if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
796              {              {
# Line 814  for (;;) Line 827  for (;;)
827        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
828        case OP_CBRA:        case OP_CBRA:
829        case OP_SCBRA:        case OP_SCBRA:
831        code += GET(code, 1);        code += GET(code, 1);
832        while (*code == OP_ALT)        while (*code == OP_ALT)
833          {          {
# Line 882  for (;;) Line 895  for (;;)
895        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
896        case OP_ANY:        case OP_ANY:
897        if (clen > 0 && !IS_NEWLINE(ptr))        if (clen > 0 && !IS_NEWLINE(ptr))
898          { ADD_NEW(state_offset + 1, 0); }          {
899            if (ptr + 1 >= md->end_subject &&
900                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
901                NLBLOCK->nltype == NLTYPE_FIXED &&
902                NLBLOCK->nllen == 2 &&
903                c == NLBLOCK->nl[0])
904              {
905              could_continue = partial_newline = TRUE;
906              }
907            else
908              {
910              }
911            }
912        break;        break;
913
914        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
# Line 910  for (;;) Line 936  for (;;)
936                 (ptr == end_subject - md->nllen)                 (ptr == end_subject - md->nllen)
937              ))              ))
938            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
939            else if (ptr + 1 >= md->end_subject &&
940                     (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
941                     NLBLOCK->nltype == NLTYPE_FIXED &&
942                     NLBLOCK->nllen == 2 &&
943                     c == NLBLOCK->nl[0])
944              {
945              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
946                {
947                reset_could_continue = TRUE;
948                ADD_NEW_DATA(-(state_offset + 1), 0, 1);
949                }
950              else could_continue = partial_newline = TRUE;
951              }
952          }          }
953        break;        break;
954
# Line 922  for (;;) Line 961  for (;;)
961          else if (clen == 0 ||          else if (clen == 0 ||
962              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
963            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
964            else if (ptr + 1 >= md->end_subject &&
965                     (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
966                     NLBLOCK->nltype == NLTYPE_FIXED &&
967                     NLBLOCK->nllen == 2 &&
968                     c == NLBLOCK->nl[0])
969              {
970              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
971                {
972                reset_could_continue = TRUE;
973                ADD_NEW_DATA(-(state_offset + 1), 0, 1);
974                }
975              else could_continue = partial_newline = TRUE;
976              }
977          }          }
978        else if (IS_NEWLINE(ptr))        else if (IS_NEWLINE(ptr))
979          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
# Line 954  for (;;) Line 1006  for (;;)
1006
1007          if (ptr > start_subject)          if (ptr > start_subject)
1008            {            {
1009            const uschar *temp = ptr - 1;            const pcre_uchar *temp = ptr - 1;
1010            if (temp < md->start_used_ptr) md->start_used_ptr = temp;            if (temp < md->start_used_ptr) md->start_used_ptr = temp;
1011  #ifdef SUPPORT_UTF8  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
1012            if (utf8) BACKCHAR(temp);            if (utf) { BACKCHAR(temp); }
1013  #endif  #endif
1014            GETCHARTEST(d, temp);            GETCHARTEST(d, temp);
1015  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
# Line 1009  for (;;) Line 1061  for (;;)
1061        if (clen > 0)        if (clen > 0)
1062          {          {
1063          BOOL OK;          BOOL OK;
1064            const pcre_uint32 *cp;
1065          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1066          switch(code[1])          switch(code[1])
1067            {            {
# Line 1022  for (;;) Line 1075  for (;;)
1075            break;            break;
1076
1077            case PT_GC:            case PT_GC:
1078            OK = _pcre_ucp_gentype[prop->chartype] == code[2];            OK = PRIV(ucp_gentype)[prop->chartype] == code[2];
1079            break;            break;
1080
1081            case PT_PC:            case PT_PC:
# Line 1036  for (;;) Line 1089  for (;;)
1089            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1090
1091            case PT_ALNUM:            case PT_ALNUM:
1092            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1093                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1094            break;            break;
1095
1096            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1097            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1098                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1099            break;            break;
1100
1101            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1102            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1103                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1104                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1105            break;            break;
1106
1107            case PT_WORD:            case PT_WORD:
1108            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1109                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1110                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1111            break;            break;
1112
1113              case PT_CLIST:
1114              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1115              for (;;)
1116                {
1117                if (c < *cp) { OK = FALSE; break; }
1118                if (c == *cp++) { OK = TRUE; break; }
1119                }
1120              break;
1121
1122            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1123
# Line 1084  for (;;) Line 1146  for (;;)
1146        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1147        if (clen > 0)        if (clen > 0)
1148          {          {
1149          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1150                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1151                NLBLOCK->nltype == NLTYPE_FIXED &&
1152                NLBLOCK->nllen == 2 &&
1153                c == NLBLOCK->nl[0])
1154              {
1155              could_continue = partial_newline = TRUE;
1156              }
1157            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1158              (c < 256 &&              (c < 256 &&
1159                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1160                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1107  for (;;) Line 1177  for (;;)
1178        if (clen > 0)        if (clen > 0)
1179          {          {
1180          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1181                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1182                NLBLOCK->nltype == NLTYPE_FIXED &&
1183                NLBLOCK->nllen == 2 &&
1184                c == NLBLOCK->nl[0])
1185              {
1186              could_continue = partial_newline = TRUE;
1187              }
1188            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1189              (c < 256 &&              (c < 256 &&
1190                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1191                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1129  for (;;) Line 1207  for (;;)
1208        if (clen > 0)        if (clen > 0)
1209          {          {
1210          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1211                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1212                NLBLOCK->nltype == NLTYPE_FIXED &&
1213                NLBLOCK->nllen == 2 &&
1214                c == NLBLOCK->nl[0])
1215              {
1216              could_continue = partial_newline = TRUE;
1217              }
1218            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1219              (c < 256 &&              (c < 256 &&
1220                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1221                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1149  for (;;) Line 1235  for (;;)
1235        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1236        if (clen > 0)        if (clen > 0)
1237          {          {
1238          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1239                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1240                NLBLOCK->nltype == NLTYPE_FIXED &&
1241                NLBLOCK->nllen == 2 &&
1242                c == NLBLOCK->nl[0])
1243              {
1244              could_continue = partial_newline = TRUE;
1245              }
1246            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1247              (c < 256 &&              (c < 256 &&
1248                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1249                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
1250            {            {
1251            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1252              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); }
1253            else            else
1255            }            }
# Line 1166  for (;;) Line 1260  for (;;)
1260        case OP_TYPEUPTO:        case OP_TYPEUPTO:
1261        case OP_TYPEMINUPTO:        case OP_TYPEMINUPTO:
1262        case OP_TYPEPOSUPTO:        case OP_TYPEPOSUPTO:
1264        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1265        if (clen > 0)        if (clen > 0)
1266          {          {
1267          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1268                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1269                NLBLOCK->nltype == NLTYPE_FIXED &&
1270                NLBLOCK->nllen == 2 &&
1271                c == NLBLOCK->nl[0])
1272              {
1273              could_continue = partial_newline = TRUE;
1274              }
1275            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1276              (c < 256 &&              (c < 256 &&
1277                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1278                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1181  for (;;) Line 1283  for (;;)
1283              next_active_state--;              next_active_state--;
1284              }              }
1285            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1286              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); }
1287            else            else
1289            }            }
# Line 1203  for (;;) Line 1305  for (;;)
1305        if (clen > 0)        if (clen > 0)
1306          {          {
1307          BOOL OK;          BOOL OK;
1308            const pcre_uint32 *cp;
1309          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1310          switch(code[2])          switch(code[2])
1311            {            {
# Line 1216  for (;;) Line 1319  for (;;)
1319            break;            break;
1320
1321            case PT_GC:            case PT_GC:
1322            OK = _pcre_ucp_gentype[prop->chartype] == code[3];            OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
1323            break;            break;
1324
1325            case PT_PC:            case PT_PC:
# Line 1230  for (;;) Line 1333  for (;;)
1333            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1334
1335            case PT_ALNUM:            case PT_ALNUM:
1336            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1337                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1338            break;            break;
1339
1340            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1341            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1342                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1343            break;            break;
1344
1345            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1346            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1347                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1348                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1349            break;            break;
1350
1351            case PT_WORD:            case PT_WORD:
1352            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1353                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1354                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1355            break;            break;
1356
1357              case PT_CLIST:
1358              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1359              for (;;)
1360                {
1361                if (c < *cp) { OK = FALSE; break; }
1362                if (c == *cp++) { OK = TRUE; break; }
1363                }
1364              break;
1365
1366            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1367
1368            default:            default:
# Line 1277  for (;;) Line 1389  for (;;)
1389        case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:        case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
1390        count = current_state->count;  /* Already matched */        count = current_state->count;  /* Already matched */
1391        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1392        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
1393          {          {
1394          const uschar *nptr = ptr + clen;          int lgb, rgb;
1395            const pcre_uchar *nptr = ptr + clen;
1396          int ncount = 0;          int ncount = 0;
1397          if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)          if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
1398            {            {
1399            active_count--;           /* Remove non-match possibility */            active_count--;           /* Remove non-match possibility */
1400            next_active_state--;            next_active_state--;
1401            }            }
1402            lgb = UCD_GRAPHBREAK(c);
1403          while (nptr < end_subject)          while (nptr < end_subject)
1404            {            {
1405            int nd;            dlen = 1;
1406            int ndlen = 1;            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
1407            GETCHARLEN(nd, nptr, ndlen);            rgb = UCD_GRAPHBREAK(d);
1408            if (UCD_CATEGORY(nd) != ucp_M) break;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
1409            ncount++;            ncount++;
1410            nptr += ndlen;            lgb = rgb;
1411              nptr += dlen;
1412            }            }
1413          count++;          count++;
# Line 1312  for (;;) Line 1427  for (;;)
1427          int ncount = 0;          int ncount = 0;
1428          switch (c)          switch (c)
1429            {            {
1430            case 0x000b:            case CHAR_VT:
1431            case 0x000c:            case CHAR_FF:
1432            case 0x0085:            case CHAR_NEL:
1433    #ifndef EBCDIC
1434            case 0x2028:            case 0x2028:
1435            case 0x2029:            case 0x2029:
1436    #endif  /* Not EBCDIC */
1437            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1438            goto ANYNL01;            goto ANYNL01;
1439
1440            case 0x000d:            case CHAR_CR:
1441            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
1442            /* Fall through */            /* Fall through */
1443
1444            ANYNL01:            ANYNL01:
1445            case 0x000a:            case CHAR_LF:
1446            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
1447              {              {
1448              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
# Line 1352  for (;;) Line 1469  for (;;)
1469          BOOL OK;          BOOL OK;
1470          switch (c)          switch (c)
1471            {            {
1472            case 0x000a:            VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
1473            OK = TRUE;            OK = TRUE;
1474            break;            break;
1475
# Line 1391  for (;;) Line 1502  for (;;)
1502          BOOL OK;          BOOL OK;
1503          switch (c)          switch (c)
1504            {            {
1505            case 0x09:      /* HT */            HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
1506            OK = TRUE;            OK = TRUE;
1507            break;            break;
1508
# Line 1450  for (;;) Line 1543  for (;;)
1543        if (clen > 0)        if (clen > 0)
1544          {          {
1545          BOOL OK;          BOOL OK;
1546            const pcre_uint32 *cp;
1547          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1548          switch(code[2])          switch(code[2])
1549            {            {
# Line 1463  for (;;) Line 1557  for (;;)
1557            break;            break;
1558
1559            case PT_GC:            case PT_GC:
1560            OK = _pcre_ucp_gentype[prop->chartype] == code[3];            OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
1561            break;            break;
1562
1563            case PT_PC:            case PT_PC:
# Line 1477  for (;;) Line 1571  for (;;)
1571            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1572
1573            case PT_ALNUM:            case PT_ALNUM:
1574            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1575                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1576            break;            break;
1577
1578            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1579            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1580                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1581            break;            break;
1582
1583            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1584            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1585                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1586                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1587            break;            break;
1588
1589            case PT_WORD:            case PT_WORD:
1590            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1591                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1592                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1593            break;            break;
1594
1595              case PT_CLIST:
1596              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1597              for (;;)
1598                {
1599                if (c < *cp) { OK = FALSE; break; }
1600                if (c == *cp++) { OK = TRUE; break; }
1601                }
1602              break;
1603
1604            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1605
1606            default:            default:
# Line 1533  for (;;) Line 1636  for (;;)
1636        QS2:        QS2:
1637
1639        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
1640          {          {
1641          const uschar *nptr = ptr + clen;          int lgb, rgb;
1642            const pcre_uchar *nptr = ptr + clen;
1643          int ncount = 0;          int ncount = 0;
1644          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
1645              codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)              codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
# Line 1543  for (;;) Line 1647  for (;;)
1647            active_count--;           /* Remove non-match possibility */            active_count--;           /* Remove non-match possibility */
1648            next_active_state--;            next_active_state--;
1649            }            }
1650            lgb = UCD_GRAPHBREAK(c);
1651          while (nptr < end_subject)          while (nptr < end_subject)
1652            {            {
1653            int nd;            dlen = 1;
1654            int ndlen = 1;            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
1655            GETCHARLEN(nd, nptr, ndlen);            rgb = UCD_GRAPHBREAK(d);
1656            if (UCD_CATEGORY(nd) != ucp_M) break;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
1657            ncount++;            ncount++;
1658            nptr += ndlen;            lgb = rgb;
1659              nptr += dlen;
1660            }            }
1662          }          }
# Line 1576  for (;;) Line 1682  for (;;)
1682          int ncount = 0;          int ncount = 0;
1683          switch (c)          switch (c)
1684            {            {
1685            case 0x000b:            case CHAR_VT:
1686            case 0x000c:            case CHAR_FF:
1687            case 0x0085:            case CHAR_NEL:
1688    #ifndef EBCDIC
1689            case 0x2028:            case 0x2028:
1690            case 0x2029:            case 0x2029:
1691    #endif  /* Not EBCDIC */
1692            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1693            goto ANYNL02;            goto ANYNL02;
1694
1695            case 0x000d:            case CHAR_CR:
1696            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
1697            /* Fall through */            /* Fall through */
1698
1699            ANYNL02:            ANYNL02:
1700            case 0x000a:            case CHAR_LF:
1701            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
1702                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
1703              {              {
# Line 1624  for (;;) Line 1732  for (;;)
1732          BOOL OK;          BOOL OK;
1733          switch (c)          switch (c)
1734            {            {
1735            case 0x000a:            VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
1736            OK = TRUE;            OK = TRUE;
1737            break;            break;
1738
# Line 1670  for (;;) Line 1772  for (;;)
1772          BOOL OK;          BOOL OK;
1773          switch (c)          switch (c)
1774            {            {
1775            case 0x09:      /* HT */            HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
1776            OK = TRUE;            OK = TRUE;
1777            break;            break;
1778
# Line 1717  for (;;) Line 1801  for (;;)
1801        case OP_PROP_EXTRA + OP_TYPEMINUPTO:        case OP_PROP_EXTRA + OP_TYPEMINUPTO:
1802        case OP_PROP_EXTRA + OP_TYPEPOSUPTO:        case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
1803        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
1804          { ADD_ACTIVE(state_offset + 6, 0); }          { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); }
1805        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1806        if (clen > 0)        if (clen > 0)
1807          {          {
1808          BOOL OK;          BOOL OK;
1809            const pcre_uint32 *cp;
1810          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1811          switch(code[4])          switch(code[1 + IMM2_SIZE + 1])
1812            {            {
1813            case PT_ANY:            case PT_ANY:
1814            OK = TRUE;            OK = TRUE;
# Line 1735  for (;;) Line 1820  for (;;)
1820            break;            break;
1821
1822            case PT_GC:            case PT_GC:
1823            OK = _pcre_ucp_gentype[prop->chartype] == code[5];            OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2];
1824            break;            break;
1825
1826            case PT_PC:            case PT_PC:
1827            OK = prop->chartype == code[5];            OK = prop->chartype == code[1 + IMM2_SIZE + 2];
1828            break;            break;
1829
1830            case PT_SC:            case PT_SC:
1831            OK = prop->script == code[5];            OK = prop->script == code[1 + IMM2_SIZE + 2];
1832            break;            break;
1833
1834            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1835
1836            case PT_ALNUM:            case PT_ALNUM:
1837            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1838                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1839            break;            break;
1840
1841            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1842            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1843                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1844            break;            break;
1845
1846            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1847            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1848                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1849                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1850            break;            break;
1851
1852            case PT_WORD:            case PT_WORD:
1853            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1854                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1855                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1856            break;            break;
1857
1858              case PT_CLIST:
1859              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1860              for (;;)
1861                {
1862                if (c < *cp) { OK = FALSE; break; }
1863                if (c == *cp++) { OK = TRUE; break; }
1864                }
1865              break;
1866
1867            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1868
1869            default:            default:
# Line 1785  for (;;) Line 1879  for (;;)
1879              next_active_state--;              next_active_state--;
1880              }              }
1881            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1882              { ADD_NEW(state_offset + 6, 0); }              { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); }
1883            else            else
1885            }            }
# Line 1798  for (;;) Line 1892  for (;;)
1892        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
1893        case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
1894        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
1895          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1896        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1897        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
1898          {          {
1899          const uschar *nptr = ptr + clen;          int lgb, rgb;
1900            const pcre_uchar *nptr = ptr + clen;
1901          int ncount = 0;          int ncount = 0;
1902          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
1903            {            {
1904            active_count--;           /* Remove non-match possibility */            active_count--;           /* Remove non-match possibility */
1905            next_active_state--;            next_active_state--;
1906            }            }
1907            lgb = UCD_GRAPHBREAK(c);
1908          while (nptr < end_subject)          while (nptr < end_subject)
1909            {            {
1910            int nd;            dlen = 1;
1911            int ndlen = 1;            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
1912            GETCHARLEN(nd, nptr, ndlen);            rgb = UCD_GRAPHBREAK(d);
1913            if (UCD_CATEGORY(nd) != ucp_M) break;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
1914            ncount++;            ncount++;
1915            nptr += ndlen;            lgb = rgb;
1916              nptr += dlen;
1917            }            }
1918            if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
1919                reset_could_continue = TRUE;
1920          if (++count >= GET2(code, 1))          if (++count >= GET2(code, 1))
1921            { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }            { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
1922          else          else
1924          }          }
# Line 1832  for (;;) Line 1931  for (;;)
1931        case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:        case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
1932        case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:        case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
1933        if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
1934          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1935        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1936        if (clen > 0)        if (clen > 0)
1937          {          {
1938          int ncount = 0;          int ncount = 0;
1939          switch (c)          switch (c)
1940            {            {
1941            case 0x000b:            case CHAR_VT:
1942            case 0x000c:            case CHAR_FF:
1943            case 0x0085:            case CHAR_NEL:
1944    #ifndef EBCDIC
1945            case 0x2028:            case 0x2028:
1946            case 0x2029:            case 0x2029:
1947    #endif  /* Not EBCDIC */
1948            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1949            goto ANYNL03;            goto ANYNL03;
1950
1951            case 0x000d:            case CHAR_CR:
1952            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
1953            /* Fall through */            /* Fall through */
1954
1955            ANYNL03:            ANYNL03:
1956            case 0x000a:            case CHAR_LF:
1957            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
1958              {              {
1959              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
1960              next_active_state--;              next_active_state--;
1961              }              }
1962            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1963              { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
1964            else            else
1966            break;            break;
# Line 1876  for (;;) Line 1977  for (;;)
1977        case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:        case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
1978        case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:        case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
1979        if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
1980          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1981        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1982        if (clen > 0)        if (clen > 0)
1983          {          {
1984          BOOL OK;          BOOL OK;
1985          switch (c)          switch (c)
1986            {            {
1987            case 0x000a:            VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
1988            OK = TRUE;            OK = TRUE;
1989            break;            break;
1990
# Line 1905  for (;;) Line 2000  for (;;)
2000              next_active_state--;              next_active_state--;
2001              }              }
2002            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2003              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
2004            else            else
2006            }            }
# Line 1918  for (;;) Line 2013  for (;;)
2013        case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:        case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
2014        case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:        case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
2015        if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
2016          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
2017        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2018        if (clen > 0)        if (clen > 0)
2019          {          {
2020          BOOL OK;          BOOL OK;
2021          switch (c)          switch (c)
2022            {            {
2023            case 0x09:      /* HT */            HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
2024            OK = TRUE;            OK = TRUE;
2025            break;            break;
2026
# Line 1960  for (;;) Line 2037  for (;;)
2037              next_active_state--;              next_active_state--;
2038              }              }
2039            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2040              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
2041            else            else
2043            }            }
# Line 1982  for (;;) Line 2059  for (;;)
2059        case OP_CHARI:        case OP_CHARI:
2060        if (clen == 0) break;        if (clen == 0) break;
2061
2062  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2063        if (utf8)        if (utf)
2064          {          {
2065          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
2066            {            {
2067            unsigned int othercase;            unsigned int othercase;
2068            if (c < 128) othercase = fcc[c]; else            if (c < 128)
2069                othercase = fcc[c];
2070            /* If we have Unicode property support, we can use it to test the            else
2071            other case of the character. */              /* If we have Unicode property support, we can use it to test the
2072                other case of the character. */
2073  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2074            othercase = UCD_OTHERCASE(c);              othercase = UCD_OTHERCASE(c);
2075  #else  #else
2076            othercase = NOTACHAR;              othercase = NOTACHAR;
2077  #endif  #endif
2078
2079            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
2080            }            }
2081          }          }
2082        else        else
2083  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2084          /* Not UTF mode */
/* Non-UTF-8 mode */
2085          {          {
2086          if (lcc[c] == lcc[d]) { ADD_NEW(state_offset + 2, 0); }          if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
2087              { ADD_NEW(state_offset + 2, 0); }
2088          }          }
2089        break;        break;
2090
# Line 2019  for (;;) Line 2096  for (;;)
2096        to wait for them to pass before continuing. */        to wait for them to pass before continuing. */
2097
2098        case OP_EXTUNI:        case OP_EXTUNI:
2099        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
2100          {          {
2101          const uschar *nptr = ptr + clen;          int lgb, rgb;
2102            const pcre_uchar *nptr = ptr + clen;
2103          int ncount = 0;          int ncount = 0;
2104            lgb = UCD_GRAPHBREAK(c);
2105          while (nptr < end_subject)          while (nptr < end_subject)
2106            {            {
2107            int nclen = 1;            dlen = 1;
2108            GETCHARLEN(c, nptr, nclen);            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
2109            if (UCD_CATEGORY(c) != ucp_M) break;            rgb = UCD_GRAPHBREAK(d);
2110              if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
2111            ncount++;            ncount++;
2112            nptr += nclen;            lgb = rgb;
2113              nptr += dlen;
2114            }            }
2115            if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
2116                reset_could_continue = TRUE;
2118          }          }
2119        break;        break;
# Line 2044  for (;;) Line 2127  for (;;)
2127        case OP_ANYNL:        case OP_ANYNL:
2128        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2129          {          {
2130          case 0x000b:          case CHAR_VT:
2131          case 0x000c:          case CHAR_FF:
2132          case 0x0085:          case CHAR_NEL:
2133    #ifndef EBCDIC
2134          case 0x2028:          case 0x2028:
2135          case 0x2029:          case 0x2029:
2136    #endif  /* Not EBCDIC */
2137          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
2138
2139          case 0x000a:          case CHAR_LF:
2141          break;          break;
2142
2143          case 0x000d:          case CHAR_CR:
2144          if (ptr + 1 < end_subject && ptr[1] == 0x0a)          if (ptr + 1 >= end_subject)
2145              {
2147              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
2148                reset_could_continue = TRUE;
2149              }
2150            else if (RAWUCHARTEST(ptr + 1) == CHAR_LF)
2151            {            {
2153            }            }
# Line 2072  for (;;) Line 2163  for (;;)
2163        case OP_NOT_VSPACE:        case OP_NOT_VSPACE:
2164        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2165          {          {
2166          case 0x000a:          VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
2167          break;          break;
2168
2169          default:          default:
# Line 2091  for (;;) Line 2176  for (;;)
2176        case OP_VSPACE:        case OP_VSPACE:
2177        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2178          {          {
2179          case 0x000a:          VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
2181          break;          break;
2182
2183          default: break;          default:
2184            break;
2185          }          }
2186        break;        break;
2187
# Line 2109  for (;;) Line 2189  for (;;)
2189        case OP_NOT_HSPACE:        case OP_NOT_HSPACE:
2190        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2191          {          {
2192          case 0x09:      /* HT */          HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
2193          break;          break;
2194
2195          default:          default:
# Line 2140  for (;;) Line 2202  for (;;)
2202        case OP_HSPACE:        case OP_HSPACE:
2203        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2204          {          {
2205          case 0x09:      /* HT */          HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
2207          break;          break;
2208
2209            default:
2210            break;
2211          }          }
2212        break;        break;
2213
2214        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2215        /* Match a negated single character casefully. This is only used for        /* Match a negated single character casefully. */
one-byte characters, that is, we know that d < 256. The character we are
checking (c) can be multibyte. */
2216
2217        case OP_NOT:        case OP_NOT:
2218        if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }        if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
2219        break;        break;
2220
2221        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2222        /* Match a negated single character caselessly. This is only used for        /* Match a negated single character caselessly. */
one-byte characters, that is, we know that d < 256. The character we are
checking (c) can be multibyte. */
2223
2224        case OP_NOTI:        case OP_NOTI:
2225        if (clen > 0 && c != d && c != fcc[d])        if (clen > 0)
2226          { ADD_NEW(state_offset + dlen + 1, 0); }          {
2227            unsigned int otherd;
2228    #ifdef SUPPORT_UTF
2229            if (utf && d >= 128)
2230              {
2231    #ifdef SUPPORT_UCP
2232              otherd = UCD_OTHERCASE(d);
2233    #endif  /* SUPPORT_UCP */
2234              }
2235            else
2236    #endif  /* SUPPORT_UTF */
2237            otherd = TABLE_GET(d, fcc, d);
2238            if (c != d && c != otherd)
2239              { ADD_NEW(state_offset + dlen + 1, 0); }
2240            }
2241        break;        break;
2242
2243        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
# Line 2192  for (;;) Line 2249  for (;;)
2249        case OP_NOTPOSPLUSI:        case OP_NOTPOSPLUSI:
2250        caseless = TRUE;        caseless = TRUE;
2251        codevalue -= OP_STARI - OP_STAR;        codevalue -= OP_STARI - OP_STAR;
2252
2253        /* Fall through */        /* Fall through */
2254        case OP_PLUS:        case OP_PLUS:
2255        case OP_MINPLUS:        case OP_MINPLUS:
# Line 2204  for (;;) Line 2261  for (;;)
2261        if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
2262        if (clen > 0)        if (clen > 0)
2263          {          {
2264          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2265          if (caseless)          if (caseless)
2266            {            {
2267  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2268            if (utf8 && d >= 128)            if (utf && d >= 128)
2269              {              {
2270  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2271              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2272  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2273              }              }
2274            else            else
2275  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2276            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2277            }            }
2278          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2279            {            {
# Line 2251  for (;;) Line 2308  for (;;)
2308        ADD_ACTIVE(state_offset + dlen + 1, 0);        ADD_ACTIVE(state_offset + dlen + 1, 0);
2309        if (clen > 0)        if (clen > 0)
2310          {          {
2311          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2312          if (caseless)          if (caseless)
2313            {            {
2314  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2315            if (utf8 && d >= 128)            if (utf && d >= 128)
2316              {              {
2317  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2318              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2319  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2320              }              }
2321            else            else
2322  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2323            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2324            }            }
2325          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2326            {            {
# Line 2296  for (;;) Line 2353  for (;;)
2353        ADD_ACTIVE(state_offset + dlen + 1, 0);        ADD_ACTIVE(state_offset + dlen + 1, 0);
2354        if (clen > 0)        if (clen > 0)
2355          {          {
2356          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2357          if (caseless)          if (caseless)
2358            {            {
2359  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2360            if (utf8 && d >= 128)            if (utf && d >= 128)
2361              {              {
2362  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2363              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2364  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2365              }              }
2366            else            else
2367  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2368            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2369            }            }
2370          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2371            {            {
# Line 2333  for (;;) Line 2390  for (;;)
2390        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2391        if (clen > 0)        if (clen > 0)
2392          {          {
2393          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2394          if (caseless)          if (caseless)
2395            {            {
2396  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2397            if (utf8 && d >= 128)            if (utf && d >= 128)
2398              {              {
2399  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2400              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2401  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2402              }              }
2403            else            else
2404  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2405            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2406            }            }
2407          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2408            {            {
2409            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2410              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
2411            else            else
2413            }            }
# Line 2373  for (;;) Line 2430  for (;;)
2430        case OP_NOTUPTO:        case OP_NOTUPTO:
2431        case OP_NOTMINUPTO:        case OP_NOTMINUPTO:
2432        case OP_NOTPOSUPTO:        case OP_NOTPOSUPTO:
2433        ADD_ACTIVE(state_offset + dlen + 3, 0);        ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0);
2434        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2435        if (clen > 0)        if (clen > 0)
2436          {          {
2437          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2438          if (caseless)          if (caseless)
2439            {            {
2440  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2441            if (utf8 && d >= 128)            if (utf && d >= 128)
2442              {              {
2443  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2444              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2445  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2446              }              }
2447            else            else
2448  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2449            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2450            }            }
2451          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2452            {            {
# Line 2399  for (;;) Line 2456  for (;;)
2456              next_active_state--;              next_active_state--;
2457              }              }
2458            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2459              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
2460            else            else
2462            }            }
# Line 2416  for (;;) Line 2473  for (;;)
2473          {          {
2474          BOOL isinclass = FALSE;          BOOL isinclass = FALSE;
2475          int next_state_offset;          int next_state_offset;
2476          const uschar *ecode;          const pcre_uchar *ecode;
2477
2478          /* For a simple class, there is always just a 32-byte table, and we          /* For a simple class, there is always just a 32-byte table, and we
2479          can set isinclass from it. */          can set isinclass from it. */
2480
2481          if (codevalue != OP_XCLASS)          if (codevalue != OP_XCLASS)
2482            {            {
2483            ecode = code + 33;            ecode = code + 1 + (32 / sizeof(pcre_uchar));
2484            if (clen > 0)            if (clen > 0)
2485              {              {
2486              isinclass = (c > 255)? (codevalue == OP_NCLASS) :              isinclass = (c > 255)? (codevalue == OP_NCLASS) :
2487                ((code[1 + c/8] & (1 << (c&7))) != 0);                ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0);
2488              }              }
2489            }            }
2490
# Line 2438  for (;;) Line 2495  for (;;)
2495          else          else
2496           {           {
2497           ecode = code + GET(code, 1);           ecode = code + GET(code, 1);
2498           if (clen > 0) isinclass = _pcre_xclass(c, code + 1 + LINK_SIZE);           if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);
2499           }           }
2500
2501          /* At this point, isinclass is set for all kinds of class, and ecode          /* At this point, isinclass is set for all kinds of class, and ecode
# Line 2472  for (;;) Line 2529  for (;;)
2529            case OP_CRMINRANGE:            case OP_CRMINRANGE:
2530            count = current_state->count;  /* Already matched */            count = current_state->count;  /* Already matched */
2531            if (count >= GET2(ecode, 1))            if (count >= GET2(ecode, 1))
2532              { ADD_ACTIVE(next_state_offset + 5, 0); }              { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
2533            if (isinclass)            if (isinclass)
2534              {              {
2535              int max = GET2(ecode, 3);              int max = GET2(ecode, 1 + IMM2_SIZE);
2536              if (++count >= max && max != 0)   /* Max 0 => no limit */              if (++count >= max && max != 0)   /* Max 0 => no limit */
2537                { ADD_NEW(next_state_offset + 5, 0); }                { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
2538              else              else
2540              }              }
# Line 2508  for (;;) Line 2565  for (;;)
2565          int rc;          int rc;
2566          int local_offsets[2];          int local_offsets[2];
2567          int local_workspace[1000];          int local_workspace[1000];
2568          const uschar *endasscode = code + GET(code, 1);          const pcre_uchar *endasscode = code + GET(code, 1);
2569
2570          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
2571
# Line 2545  for (;;) Line 2602  for (;;)
2603            {            {
2604            rrc = 0;            rrc = 0;
2605            if (pcre_callout != NULL)            if (PUBL(callout) != NULL)
2606              {              {
2607              pcre_callout_block cb;              PUBL(callout_block) cb;
2608              cb.version          = 1;   /* Version 1 of the callout block */              cb.version          = 1;   /* Version 1 of the callout block */
2610              cb.offset_vector    = offsets;              cb.offset_vector    = offsets;
2611    #if defined COMPILE_PCRE8
2612              cb.subject          = (PCRE_SPTR)start_subject;              cb.subject          = (PCRE_SPTR)start_subject;
2613    #elif defined COMPILE_PCRE16
2614                cb.subject          = (PCRE_SPTR16)start_subject;
2615    #elif defined COMPILE_PCRE32
2616                cb.subject          = (PCRE_SPTR32)start_subject;
2617    #endif
2618              cb.subject_length   = (int)(end_subject - start_subject);              cb.subject_length   = (int)(end_subject - start_subject);
2619              cb.start_match      = (int)(current_subject - start_subject);              cb.start_match      = (int)(current_subject - start_subject);
2620              cb.current_position = (int)(ptr - start_subject);              cb.current_position = (int)(ptr - start_subject);
# Line 2560  for (;;) Line 2623  for (;;)
2623              cb.capture_top      = 1;              cb.capture_top      = 1;
2624              cb.capture_last     = -1;              cb.capture_last     = -1;
2625              cb.callout_data     = md->callout_data;              cb.callout_data     = md->callout_data;
2626              cb.mark             = NULL;   /* No (*MARK) support */              cb.mark             = NULL;   /* No (*MARK) support */
2627              if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */              if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
2628              }              }
2629            if (rrc > 0) break;                      /* Fail this thread */            if (rrc > 0) break;                      /* Fail this thread */
2630            code += _pcre_OP_lengths[OP_CALLOUT];    /* Skip callout data */            code += PRIV(OP_lengths)[OP_CALLOUT];    /* Skip callout data */
2631            }            }
2632
# Line 2585  for (;;) Line 2648  for (;;)
2648
2649          else if (condcode == OP_RREF || condcode == OP_NRREF)          else if (condcode == OP_RREF || condcode == OP_NRREF)
2650            {            {
2651            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE + 2);
2652            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
2653            if (md->recursive != NULL)            if (md->recursive != NULL)
2656            }            }
2657
# Line 2597  for (;;) Line 2660  for (;;)
2660          else          else
2661            {            {
2662            int rc;            int rc;
2663            const uschar *asscode = code + LINK_SIZE + 1;            const pcre_uchar *asscode = code + LINK_SIZE + 1;
2664            const uschar *endasscode = asscode + GET(asscode, 1);            const pcre_uchar *endasscode = asscode + GET(asscode, 1);
2665
2666            while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);            while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
2667
# Line 2626  for (;;) Line 2689  for (;;)
2689        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2690        case OP_RECURSE:        case OP_RECURSE:
2691          {          {
2692          dfa_recursion_info *ri;          dfa_recursion_info *ri;
2693          int local_offsets[1000];          int local_offsets[1000];
2694          int local_workspace[1000];          int local_workspace[1000];
2695          const uschar *callpat = start_code + GET(code, 1);          const pcre_uchar *callpat = start_code + GET(code, 1);
2696          int recno = (callpat == md->start_code)? 0 :          int recno = (callpat == md->start_code)? 0 :
2698          int rc;          int rc;
2699
2700          DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP));          DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP));
2701
2702          /* Check for repeating a recursion without advancing the subject          /* Check for repeating a recursion without advancing the subject
2703          pointer. This should catch convoluted mutual recursions. (Some simple          pointer. This should catch convoluted mutual recursions. (Some simple
2704          cases are caught at compile time.) */          cases are caught at compile time.) */

for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
if (recno == ri->group_num && ptr == ri->subject_position)
return PCRE_ERROR_RECURSELOOP;
2705
2706          /* Remember this recursion and where we started it so as to          for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
2707              if (recno == ri->group_num && ptr == ri->subject_position)
2708                return PCRE_ERROR_RECURSELOOP;
2709
2710            /* Remember this recursion and where we started it so as to
2711          catch infinite loops. */          catch infinite loops. */
2712
2713          new_recursive.group_num = recno;          new_recursive.group_num = recno;
2714          new_recursive.subject_position = ptr;          new_recursive.subject_position = ptr;
2715          new_recursive.prevrec = md->recursive;          new_recursive.prevrec = md->recursive;
2716          md->recursive = &new_recursive;          md->recursive = &new_recursive;
2717
2718          rc = internal_dfa_exec(          rc = internal_dfa_exec(
2719            md,                                   /* fixed match data */            md,                                   /* fixed match data */
# Line 2665  for (;;) Line 2728  for (;;)
2728
2729          md->recursive = new_recursive.prevrec;  /* Done this recursion */          md->recursive = new_recursive.prevrec;  /* Done this recursion */
2730
2731          DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP,          DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP,
2732            rc));            rc));
2733
2734          /* Ran out of internal offsets */          /* Ran out of internal offsets */
# Line 2680  for (;;) Line 2743  for (;;)
2743            {            {
2744            for (rc = rc*2 - 2; rc >= 0; rc -= 2)            for (rc = rc*2 - 2; rc >= 0; rc -= 2)
2745              {              {
const uschar *p = start_subject + local_offsets[rc];
const uschar *pp = start_subject + local_offsets[rc+1];
2746              int charcount = local_offsets[rc+1] - local_offsets[rc];              int charcount = local_offsets[rc+1] - local_offsets[rc];
2747              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2748                if (utf)
2749                  {
2750                  const pcre_uchar *p = start_subject + local_offsets[rc];
2751                  const pcre_uchar *pp = start_subject + local_offsets[rc+1];
2752                  while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2753                  }
2754    #endif
2755              if (charcount > 0)              if (charcount > 0)
2756                {                {
# Line 2703  for (;;) Line 2771  for (;;)
2771        case OP_SBRAPOS:        case OP_SBRAPOS:
2772        case OP_CBRAPOS:        case OP_CBRAPOS:
2773        case OP_SCBRAPOS:        case OP_SCBRAPOS:
2774        case OP_BRAPOSZERO:        case OP_BRAPOSZERO:
2775          {          {
2776          int charcount, matched_count;          int charcount, matched_count;
2777          const uschar *local_ptr = ptr;          const pcre_uchar *local_ptr = ptr;
2778          BOOL allow_zero;          BOOL allow_zero;
2779
2780          if (codevalue == OP_BRAPOSZERO)          if (codevalue == OP_BRAPOSZERO)
2781            {            {
2782            allow_zero = TRUE;            allow_zero = TRUE;
2783            codevalue = *(++code);  /* Codevalue will be one of above BRAs */            codevalue = *(++code);  /* Codevalue will be one of above BRAs */
2784            }            }
2785          else allow_zero = FALSE;          else allow_zero = FALSE;
2786
2787          /* Loop to match the subpattern as many times as possible as if it were          /* Loop to match the subpattern as many times as possible as if it were
2788          a complete pattern. */          a complete pattern. */
2789
2790          for (matched_count = 0;; matched_count++)          for (matched_count = 0;; matched_count++)
2791            {            {
2792            int local_offsets[2];            int local_offsets[2];
2793            int local_workspace[1000];            int local_workspace[1000];
2794
2795            int rc = internal_dfa_exec(            int rc = internal_dfa_exec(
2796              md,                                   /* fixed match data */              md,                                   /* fixed match data */
2797              code,                                 /* this subexpression's code */              code,                                 /* this subexpression's code */
# Line 2734  for (;;) Line 2802  for (;;)
2802              local_workspace,                      /* workspace vector */              local_workspace,                      /* workspace vector */
2803              sizeof(local_workspace)/sizeof(int),  /* size of same */              sizeof(local_workspace)/sizeof(int),  /* size of same */
2804              rlevel);                              /* function recursion level */              rlevel);                              /* function recursion level */
2805
2806            /* Failed to match */            /* Failed to match */
2807
2808            if (rc < 0)            if (rc < 0)
2809              {              {
2810              if (rc != PCRE_ERROR_NOMATCH) return rc;              if (rc != PCRE_ERROR_NOMATCH) return rc;
2811              break;              break;
2812              }              }
2813
2814            /* Matched: break the loop if zero characters matched. */            /* Matched: break the loop if zero characters matched. */
2815
2816            charcount = local_offsets[1] - local_offsets[0];            charcount = local_offsets[1] - local_offsets[0];
2817            if (charcount == 0) break;            if (charcount == 0) break;
2818            local_ptr += charcount;    /* Advance temporary position ptr */            local_ptr += charcount;    /* Advance temporary position ptr */
2819            }            }
2820
2821          /* At this point we have matched the subpattern matched_count          /* At this point we have matched the subpattern matched_count
2822          times, and local_ptr is pointing to the character after the end of the          times, and local_ptr is pointing to the character after the end of the
2823          last match. */          last match. */
2824
2825          if (matched_count > 0 || allow_zero)          if (matched_count > 0 || allow_zero)
2826            {            {
2827            const uschar *end_subpattern = code;            const pcre_uchar *end_subpattern = code;
2828            int next_state_offset;            int next_state_offset;
2829
2830            do { end_subpattern += GET(end_subpattern, 1); }            do { end_subpattern += GET(end_subpattern, 1); }
2831              while (*end_subpattern == OP_ALT);              while (*end_subpattern == OP_ALT);
2832            next_state_offset =            next_state_offset =
# Line 2777  for (;;) Line 2845  for (;;)
2845              }              }
2846            else            else
2847              {              {
2848              const uschar *p = ptr;              const pcre_uchar *p = ptr;
2849              const uschar *pp = local_ptr;              const pcre_uchar *pp = local_ptr;
2850              charcount = pp - p;              charcount = (int)(pp - p);
2851              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2852                if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2853    #endif
2855              }              }
2856            }            }
2857          }          }
2858        break;        break;
2859
2860        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2861        case OP_ONCE:        case OP_ONCE:
2862          case OP_ONCE_NC:
2863          {          {
2864          int local_offsets[2];          int local_offsets[2];
2865          int local_workspace[1000];          int local_workspace[1000];
# Line 2806  for (;;) Line 2877  for (;;)
2877
2878          if (rc >= 0)          if (rc >= 0)
2879            {            {
2880            const uschar *end_subpattern = code;            const pcre_uchar *end_subpattern = code;
2881            int charcount = local_offsets[1] - local_offsets[0];            int charcount = local_offsets[1] - local_offsets[0];
2882            int next_state_offset, repeat_state_offset;            int next_state_offset, repeat_state_offset;
2883
# Line 2859  for (;;) Line 2930  for (;;)
2930              }              }
2931            else            else
2932              {              {
2933              const uschar *p = start_subject + local_offsets[0];  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2934              const uschar *pp = start_subject + local_offsets[1];              if (utf)
2935              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;                {
2936                  const pcre_uchar *p = start_subject + local_offsets[0];
2937                  const pcre_uchar *pp = start_subject + local_offsets[1];
2938                  while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2939                  }
2940    #endif
2942              if (repeat_state_offset >= 0)              if (repeat_state_offset >= 0)
2943                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
# Line 2877  for (;;) Line 2953  for (;;)
2953
2954        case OP_CALLOUT:        case OP_CALLOUT:
2955        rrc = 0;        rrc = 0;
2956        if (pcre_callout != NULL)        if (PUBL(callout) != NULL)
2957          {          {
2958          pcre_callout_block cb;          PUBL(callout_block) cb;
2959          cb.version          = 1;   /* Version 1 of the callout block */          cb.version          = 1;   /* Version 1 of the callout block */
2960          cb.callout_number   = code[1];          cb.callout_number   = code[1];
2961          cb.offset_vector    = offsets;          cb.offset_vector    = offsets;
2962    #if defined COMPILE_PCRE8
2963          cb.subject          = (PCRE_SPTR)start_subject;          cb.subject          = (PCRE_SPTR)start_subject;
2964    #elif defined COMPILE_PCRE16
2965            cb.subject          = (PCRE_SPTR16)start_subject;
2966    #elif defined COMPILE_PCRE32
2967            cb.subject          = (PCRE_SPTR32)start_subject;
2968    #endif
2969          cb.subject_length   = (int)(end_subject - start_subject);          cb.subject_length   = (int)(end_subject - start_subject);
2970          cb.start_match      = (int)(current_subject - start_subject);          cb.start_match      = (int)(current_subject - start_subject);
2971          cb.current_position = (int)(ptr - start_subject);          cb.current_position = (int)(ptr - start_subject);
# Line 2892  for (;;) Line 2974  for (;;)
2974          cb.capture_top      = 1;          cb.capture_top      = 1;
2975          cb.capture_last     = -1;          cb.capture_last     = -1;
2976          cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
2977          cb.mark             = NULL;   /* No (*MARK) support */          cb.mark             = NULL;   /* No (*MARK) support */
2978          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */          if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
2979          }          }
2980        if (rrc == 0)        if (rrc == 0)
2981          { ADD_ACTIVE(state_offset + _pcre_OP_lengths[OP_CALLOUT], 0); }          { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); }
2982        break;        break;
2983
2984
# Line 2925  for (;;) Line 3007  for (;;)
3007    if (new_count <= 0)    if (new_count <= 0)
3008      {      {
3009      if (rlevel == 1 &&                               /* Top level, and */      if (rlevel == 1 &&                               /* Top level, and */
3010          could_continue &&                            /* Some could go on */          could_continue &&                            /* Some could go on, and */
3011          forced_fail != workspace[1] &&               /* Not all forced fail & */          forced_fail != workspace[1] &&               /* Not all forced fail & */
3012          (                                            /* either... */          (                                            /* either... */
3013          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
# Line 2933  for (;;) Line 3015  for (;;)
3015          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
3016           match_count < 0)                            /* no matches */           match_count < 0)                            /* no matches */
3017          ) &&                                         /* And... */          ) &&                                         /* And... */
3018          ptr >= end_subject &&                  /* Reached end of subject */          (
3019          ptr > md->start_used_ptr)              /* Inspected non-empty string */          partial_newline ||                           /* Either partial NL */
3020              (                                          /* or ... */
3021              ptr >= end_subject &&                /* End of subject and */
3022              ptr > md->start_used_ptr)            /* Inspected non-empty string */
3023              )
3024            )
3025        {        {
3026        if (offsetcount >= 2)        if (offsetcount >= 2)
3027          {          {
# Line 2993  Returns:          > 0 => number of match Line 3080  Returns:          > 0 => number of match
3080                   < -1 => some kind of unexpected problem                   < -1 => some kind of unexpected problem
3081  */  */
3082
3083    #if defined COMPILE_PCRE8
3084  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3085  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
3086    const char *subject, int length, int start_offset, int options, int *offsets,    const char *subject, int length, int start_offset, int options, int *offsets,
3087    int offsetcount, int *workspace, int wscount)    int offsetcount, int *workspace, int wscount)
3088    #elif defined COMPILE_PCRE16
3089    PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3090    pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
3091      PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
3092      int offsetcount, int *workspace, int wscount)
3093    #elif defined COMPILE_PCRE32
3094    PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3095    pcre32_dfa_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
3096      PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
3097      int offsetcount, int *workspace, int wscount)
3098    #endif
3099  {  {
3100  real_pcre *re = (real_pcre *)argument_re;  REAL_PCRE *re = (REAL_PCRE *)argument_re;
3101  dfa_match_data match_block;  dfa_match_data match_block;
3102  dfa_match_data *md = &match_block;  dfa_match_data *md = &match_block;
3103  BOOL utf8, anchored, startline, firstline;  BOOL utf, anchored, startline, firstline;
3104  const uschar *current_subject, *end_subject, *lcc;  const pcre_uchar *current_subject, *end_subject;

pcre_study_data internal_study;
3105  const pcre_study_data *study = NULL;  const pcre_study_data *study = NULL;
real_pcre internal_re;
3106
3107  const uschar *req_byte_ptr;  const pcre_uchar *req_char_ptr;
3108  const uschar *start_bits = NULL;  const pcre_uint8 *start_bits = NULL;
3109  BOOL first_byte_caseless = FALSE;  BOOL has_first_char = FALSE;
3110  BOOL req_byte_caseless = FALSE;  BOOL has_req_char = FALSE;
3111  int first_byte = -1;  pcre_uchar first_char = 0;
3112  int req_byte = -1;  pcre_uchar first_char2 = 0;
3113  int req_byte2 = -1;  pcre_uchar req_char = 0;
3114    pcre_uchar req_char2 = 0;
3115  int newline;  int newline;
3116
3117  /* Plausibility checks */  /* Plausibility checks */
# Line 3026  if (offsetcount < 0) return PCRE_ERROR_B Line 3123  if (offsetcount < 0) return PCRE_ERROR_B
3123  if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;  if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
3124  if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;  if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
3125
3126  /* We need to find the pointer to any study data before we test for byte  /* Check that the first field in the block is the magic number. If it is not,
3127  flipping, so we scan the extra_data block first. This may set two fields in the  return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
3128  match block, so we must initialize them beforehand. However, the other fields  REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
3129  in the match block must not be set until after the byte flipping. */  means that the pattern is likely compiled with different endianness. */
3130
3131    if (re->magic_number != MAGIC_NUMBER)
3132      return re->magic_number == REVERSED_MAGIC_NUMBER?
3134    if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
3135
3136    /* If restarting after a partial match, do some sanity checks on the contents
3137    of the workspace. */
3138
3139    if ((options & PCRE_DFA_RESTART) != 0)
3140      {
3141      if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
3142        workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK)
3144      }
3145
3146    /* Set up study, callout, and table data */
3147
3148  md->tables = re->tables;  md->tables = re->tables;
3149  md->callout_data = NULL;  md->callout_data = NULL;
# Line 3048  if (extra_data != NULL) Line 3162  if (extra_data != NULL)
3162      md->tables = extra_data->tables;      md->tables = extra_data->tables;
3163    }    }
3164
/* Check that the first field in the block is the magic number. If it is not,
test for a regex that was compiled on a host of opposite endianness. If this is
the case, flipped values are put in internal_re and internal_study if there was
study data too. */

if (re->magic_number != MAGIC_NUMBER)
{
re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
if (re == NULL) return PCRE_ERROR_BADMAGIC;
if (study != NULL) study = &internal_study;
}

3165  /* Set some local values */  /* Set some local values */
3166
3167  current_subject = (const unsigned char *)subject + start_offset;  current_subject = (const pcre_uchar *)subject + start_offset;
3168  end_subject = (const unsigned char *)subject + length;  end_subject = (const pcre_uchar *)subject + length;
3169  req_byte_ptr = current_subject - 1;  req_char_ptr = current_subject - 1;
3170
3171  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3172  utf8 = (re->options & PCRE_UTF8) != 0;  /* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
3173    utf = (re->options & PCRE_UTF8) != 0;
3174  #else  #else
3175  utf8 = FALSE;  utf = FALSE;
3176  #endif  #endif
3177
3178  anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||  anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
# Line 3077  anchored = (options & (PCRE_ANCHORED|PCR Line 3180  anchored = (options & (PCRE_ANCHORED|PCR
3180
3181  /* The remaining fixed data for passing around. */  /* The remaining fixed data for passing around. */
3182
3183  md->start_code = (const uschar *)argument_re +  md->start_code = (const pcre_uchar *)argument_re +
3184      re->name_table_offset + re->name_count * re->name_entry_size;      re->name_table_offset + re->name_count * re->name_entry_size;
3185  md->start_subject = (const unsigned char *)subject;  md->start_subject = (const pcre_uchar *)subject;
3186  md->end_subject = end_subject;  md->end_subject = end_subject;
3187  md->start_offset = start_offset;  md->start_offset = start_offset;
3188  md->moptions = options;  md->moptions = options;
# Line 3140  else Line 3243  else
3243  /* Check a UTF-8 string if required. Unfortunately there's no way of passing  /* Check a UTF-8 string if required. Unfortunately there's no way of passing
3244  back the character offset. */  back the character offset. */
3245
3246  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3247  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)  if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
3248    {    {
3249    int erroroffset;    int erroroffset;
3250    int errorcode = _pcre_valid_utf8((uschar *)subject, length, &erroroffset);    int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset);
3251    if (errorcode != 0)    if (errorcode != 0)
3252      {      {
3253      if (offsetcount >= 2)      if (offsetcount >= 2)
3254        {        {
3255        offsets[0] = erroroffset;        offsets[0] = erroroffset;
3256        offsets[1] = errorcode;        offsets[1] = errorcode;
3257        }        }
3258      return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0)?  #if defined COMPILE_PCRE8
3259        return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0) ?
3261      }  #elif defined COMPILE_PCRE16
3262        return (errorcode <= PCRE_UTF16_ERR1 && (options & PCRE_PARTIAL_HARD) != 0) ?
3264    #elif defined COMPILE_PCRE32
3266    #endif
3267        }
3268    #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
3269    if (start_offset > 0 && start_offset < length &&    if (start_offset > 0 && start_offset < length &&
3270          (((USPTR)subject)[start_offset] & 0xc0) == 0x80)          NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
3272    #endif
3273    }    }
3274  #endif  #endif
3275
# Line 3165  if (utf8 && (options & PCRE_NO_UTF8_CHEC Line 3277  if (utf8 && (options & PCRE_NO_UTF8_CHEC
3277  is a feature that makes it possible to save compiled regex and re-use them  is a feature that makes it possible to save compiled regex and re-use them
3278  in other programs later. */  in other programs later. */
3279
3280  if (md->tables == NULL) md->tables = _pcre_default_tables;  if (md->tables == NULL) md->tables = PRIV(default_tables);
3281
3282  /* The lower casing table and the "must be at the start of a line" flag are  /* The "must be at the start of a line" flags are used in a loop when finding
3283  used in a loop when finding where to start. */  where to start. */
3284
lcc = md->tables + lcc_offset;
3285  startline = (re->flags & PCRE_STARTLINE) != 0;  startline = (re->flags & PCRE_STARTLINE) != 0;
3286  firstline = (re->options & PCRE_FIRSTLINE) != 0;  firstline = (re->options & PCRE_FIRSTLINE) != 0;
3287
# Line 3184  if (!anchored) Line 3295  if (!anchored)
3295    {    {
3296    if ((re->flags & PCRE_FIRSTSET) != 0)    if ((re->flags & PCRE_FIRSTSET) != 0)
3297      {      {
3298      first_byte = re->first_byte & 255;      has_first_char = TRUE;
3299      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)      first_char = first_char2 = (pcre_uchar)(re->first_char);
3300        first_byte = lcc[first_byte];      if ((re->flags & PCRE_FCH_CASELESS) != 0)
3301          {
3302          first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char);
3303    #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
3304          if (utf && first_char > 127)
3305            first_char2 = UCD_OTHERCASE(first_char);
3306    #endif
3307          }
3308      }      }
3309    else    else
3310      {      {
# Line 3201  character" set. */ Line 3319  character" set. */
3319
3320  if ((re->flags & PCRE_REQCHSET) != 0)  if ((re->flags & PCRE_REQCHSET) != 0)
3321    {    {
3322    req_byte = re->req_byte & 255;    has_req_char = TRUE;
3323    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;    req_char = req_char2 = (pcre_uchar)(re->req_char);
3324    req_byte2 = (md->tables + fcc_offset)[req_byte];  /* case flipped */    if ((re->flags & PCRE_RCH_CASELESS) != 0)
3325        {
3326        req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char);
3327    #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
3328        if (utf && req_char > 127)
3329          req_char2 = UCD_OTHERCASE(req_char);
3330    #endif
3331        }
3332    }    }
3333
3334  /* Call the main matching function, looping for a non-anchored regex after a  /* Call the main matching function, looping for a non-anchored regex after a
# Line 3216  for (;;) Line 3341  for (;;)
3341
3342    if ((options & PCRE_DFA_RESTART) == 0)    if ((options & PCRE_DFA_RESTART) == 0)
3343      {      {
3344      const uschar *save_end_subject = end_subject;      const pcre_uchar *save_end_subject = end_subject;
3345
3346      /* If firstline is TRUE, the start of the match is constrained to the first      /* If firstline is TRUE, the start of the match is constrained to the first
3347      line of a multiline string. Implement this by temporarily adjusting      line of a multiline string. Implement this by temporarily adjusting
# Line 3225  for (;;) Line 3350  for (;;)
3350
3351      if (firstline)      if (firstline)
3352        {        {
3353        USPTR t = current_subject;        PCRE_PUCHAR t = current_subject;
3354  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3355        if (utf8)        if (utf)
3356          {          {
3357          while (t < md->end_subject && !IS_NEWLINE(t))          while (t < md->end_subject && !IS_NEWLINE(t))
3358            {            {
3359            t++;            t++;
3360            while (t < end_subject && (*t & 0xc0) == 0x80) t++;            ACROSSCHAR(t < end_subject, *t, t++);
3361            }            }
3362          }          }
3363        else        else
# Line 3249  for (;;) Line 3374  for (;;)
3374
3375      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
3376        {        {
3377        /* Advance to a known first byte. */        /* Advance to a known first char. */
3378
3379        if (first_byte >= 0)        if (has_first_char)
3380          {          {
3381          if (first_byte_caseless)          if (first_char != first_char2)
3382              {
3383              pcre_uchar csc;
3384            while (current_subject < end_subject &&            while (current_subject < end_subject &&
3385                   lcc[*current_subject] != first_byte)                   (csc = RAWUCHARTEST(current_subject)) != first_char && csc != first_char2)
3386              current_subject++;              current_subject++;
3387              }
3388          else          else
3389            while (current_subject < end_subject &&            while (current_subject < end_subject &&
3390                   *current_subject != first_byte)                   RAWUCHARTEST(current_subject) != first_char)
3391              current_subject++;              current_subject++;
3392          }          }
3393
# Line 3269  for (;;) Line 3397  for (;;)
3397          {          {
3398          if (current_subject > md->start_subject + start_offset)          if (current_subject > md->start_subject + start_offset)
3399            {            {
3400  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3401            if (utf8)            if (utf)
3402              {              {
3403              while (current_subject < end_subject &&              while (current_subject < end_subject &&
3404                     !WAS_NEWLINE(current_subject))                     !WAS_NEWLINE(current_subject))
3405                {                {
3406                current_subject++;                current_subject++;
3407                while(current_subject < end_subject &&                ACROSSCHAR(current_subject < end_subject, *current_subject,
3408                      (*current_subject & 0xc0) == 0x80)                  current_subject++);
current_subject++;
3409                }                }
3410              }              }
3411            else            else
# Line 3290  for (;;) Line 3417  for (;;)
3417            ANYCRLF, and we are now at a LF, advance the match position by one            ANYCRLF, and we are now at a LF, advance the match position by one
3418            more character. */            more character. */
3419
3420            if (current_subject[-1] == CHAR_CR &&            if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
3421                 (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&                 (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
3422                 current_subject < end_subject &&                 current_subject < end_subject &&
3423                 *current_subject == CHAR_NL)                 RAWUCHARTEST(current_subject) == CHAR_NL)
3424              current_subject++;              current_subject++;
3425            }            }
3426          }          }
# Line 3304  for (;;) Line 3431  for (;;)
3431          {          {
3432          while (current_subject < end_subject)          while (current_subject < end_subject)
3433            {            {
3434            register unsigned int c = *current_subject;            register pcre_uint32 c = RAWUCHARTEST(current_subject);
3435    #ifndef COMPILE_PCRE8
3436              if (c > 255) c = 255;
3437    #endif
3438            if ((start_bits[c/8] & (1 << (c&7))) == 0)            if ((start_bits[c/8] & (1 << (c&7))) == 0)
3439              {              {
3440              current_subject++;              current_subject++;
3441  #ifdef SUPPORT_UTF8  #if defined SUPPORT_UTF && defined COMPILE_PCRE8
3442              if (utf8)              /* In non 8-bit mode, the iteration will stop for
3443                while(current_subject < end_subject &&              characters > 255 at the beginning or not stop at all. */
3444                      (*current_subject & 0xc0) == 0x80) current_subject++;              if (utf)
3445                  ACROSSCHAR(current_subject < end_subject, *current_subject,
3446                    current_subject++);
3447  #endif  #endif
3448              }              }
3449            else break;            else break;
# Line 3327  for (;;) Line 3459  for (;;)
3459      disabling is explicitly requested (and of course, by the test above, this      disabling is explicitly requested (and of course, by the test above, this
3460      code is not obeyed when restarting after a partial match). */      code is not obeyed when restarting after a partial match). */
3461
3462      if ((options & PCRE_NO_START_OPTIMIZE) == 0 &&      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 &&
3463          (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)          (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
3464        {        {
3465        /* If the pattern was studied, a minimum subject length may be set. This        /* If the pattern was studied, a minimum subject length may be set. This
# Line 3339  for (;;) Line 3471  for (;;)
3471            (pcre_uint32)(end_subject - current_subject) < study->minlength)            (pcre_uint32)(end_subject - current_subject) < study->minlength)
3472          return PCRE_ERROR_NOMATCH;          return PCRE_ERROR_NOMATCH;
3473
3474        /* If req_byte is set, we know that that character must appear in the        /* If req_char is set, we know that that character must appear in the
3475        subject for the match to succeed. If the first character is set, req_byte        subject for the match to succeed. If the first character is set, req_char
3476        must be later in the subject; otherwise the test starts at the match        must be later in the subject; otherwise the test starts at the match
3477        point. This optimization can save a huge amount of work in patterns with        point. This optimization can save a huge amount of work in patterns with
3478        nested unlimited repeats that aren't going to match. Writing separate        nested unlimited repeats that aren't going to match. Writing separate
# Line 3352  for (;;) Line 3484  for (;;)
3484        patterns. This showed up when somebody was matching /^C/ on a 32-megabyte        patterns. This showed up when somebody was matching /^C/ on a 32-megabyte
3485        string... so we don't do this when the string is sufficiently long. */        string... so we don't do this when the string is sufficiently long. */
3486
3487        if (req_byte >= 0 && end_subject - current_subject < REQ_BYTE_MAX)        if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX)
3488          {          {
3489          register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);          register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0);
3490
3491          /* We don't need to repeat the search if we haven't yet reached the          /* We don't need to repeat the search if we haven't yet reached the
3492          place we found it at last time. */          place we found it at last time. */
3493
3494          if (p > req_byte_ptr)          if (p > req_char_ptr)
3495            {            {
3496            if (req_byte_caseless)            if (req_char != req_char2)
3497              {              {
3498              while (p < end_subject)              while (p < end_subject)
3499                {                {
3500                register int pp = *p++;                register pcre_uint32 pp = RAWUCHARINCTEST(p);
3501                if (pp == req_byte || pp == req_byte2) { p--; break; }                if (pp == req_char || pp == req_char2) { p--; break; }
3502                }                }
3503              }              }
3504            else            else
3505              {              {
3506              while (p < end_subject)              while (p < end_subject)
3507                {                {
3508                if (*p++ == req_byte) { p--; break; }                if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
3509                }                }
3510              }              }
3511
# Line 3386  for (;;) Line 3518  for (;;)
3518            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
3519            the start hasn't passed this character yet. */            the start hasn't passed this character yet. */
3520
3521            req_byte_ptr = p;            req_char_ptr = p;
3522            }            }
3523          }          }
3524        }        }
# Line 3395  for (;;) Line 3527  for (;;)
3527    /* OK, now we can do the business */    /* OK, now we can do the business */
3528
3529    md->start_used_ptr = current_subject;    md->start_used_ptr = current_subject;
3530    md->recursive = NULL;    md->recursive = NULL;
3531
3532    rc = internal_dfa_exec(    rc = internal_dfa_exec(
3533      md,                                /* fixed match data */      md,                                /* fixed match data */
# Line 3418  for (;;) Line 3550  for (;;)
3550
3551    if (firstline && IS_NEWLINE(current_subject)) break;    if (firstline && IS_NEWLINE(current_subject)) break;
3552    current_subject++;    current_subject++;
3553    if (utf8)  #ifdef SUPPORT_UTF
3554      if (utf)
3555      {      {
3556      while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80)      ACROSSCHAR(current_subject < end_subject, *current_subject,
3557        current_subject++;        current_subject++);
3558      }      }
3559    #endif
3560    if (current_subject > end_subject) break;    if (current_subject > end_subject) break;
3561
3562    /* If we have just passed a CR and we are now at a LF, and the pattern does    /* If we have just passed a CR and we are now at a LF, and the pattern does
3563    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
3564    or ANY or ANYCRLF, advance the match position by one more character. */    or ANY or ANYCRLF, advance the match position by one more character. */
3565
3566    if (current_subject[-1] == CHAR_CR &&    if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
3567        current_subject < end_subject &&        current_subject < end_subject &&
3568        *current_subject == CHAR_NL &&        RAWUCHARTEST(current_subject) == CHAR_NL &&
3569        (re->flags & PCRE_HASCRORLF) == 0 &&        (re->flags & PCRE_HASCRORLF) == 0 &&
3570          (md->nltype == NLTYPE_ANY ||          (md->nltype == NLTYPE_ANY ||
3571           md->nltype == NLTYPE_ANYCRLF ||           md->nltype == NLTYPE_ANYCRLF ||

Legend:
 Removed from v.645 changed lines Added in v.1100