/[pcre]/code/trunk/pcre_dfa_exec.c
ViewVC logotype

Diff of /code/trunk/pcre_dfa_exec.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 728 by ph10, Mon Oct 10 16:01:03 2011 UTC revision 919 by ph10, Fri Feb 17 11:48:02 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 113  small value. Non-zero values in the tabl Line 113  small value. Non-zero values in the tabl
113  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
114  modified, the three tables that follow must also be modified. */  modified, the three tables that follow must also be modified. */
115    
116  static const uschar coptable[] = {  static const pcre_uint8 coptable[] = {
117    0,                             /* End                                    */    0,                             /* End                                    */
118    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
119    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 128  static const uschar coptable[] = {
128    1,                             /* noti                                   */    1,                             /* noti                                   */
129    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
130    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
131    3, 3, 3,                       /* upto, minupto, exact                   */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto, minupto                          */
132    1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */    1+IMM2_SIZE,                   /* exact                                  */
133      1, 1, 1, 1+IMM2_SIZE,          /* *+, ++, ?+, upto+                      */
134    1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */    1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
135    3, 3, 3,                       /* upto I, minupto I, exact I             */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto I, minupto I                      */
136    1, 1, 1, 3,                    /* *+I, ++I, ?+I, upto+I                  */    1+IMM2_SIZE,                   /* exact I                                */
137      1, 1, 1, 1+IMM2_SIZE,          /* *+I, ++I, ?+I, upto+I                  */
138    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
139    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
140    3, 3, 3,                       /* NOT upto, minupto, exact               */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto, minupto                      */
141    1, 1, 1, 3,                    /* NOT *+, ++, ?+, upto+                  */    1+IMM2_SIZE,                   /* NOT exact                              */
142      1, 1, 1, 1+IMM2_SIZE,          /* NOT *+, ++, ?+, upto+                  */
143    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          */
144    3, 3, 3,                       /* NOT upto I, minupto I, exact I         */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto I, minupto I                  */
145    1, 1, 1, 3,                    /* NOT *+I, ++I, ?+I, upto+I              */    1+IMM2_SIZE,                   /* NOT exact I                            */
146      1, 1, 1, 1+IMM2_SIZE,          /* NOT *+I, ++I, ?+I, upto+I              */
147    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
148    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
149    3, 3, 3,                       /* Type upto, minupto, exact              */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* Type upto, minupto                     */
150    1, 1, 1, 3,                    /* Type *+, ++, ?+, upto+                 */    1+IMM2_SIZE,                   /* Type exact                             */
151      1, 1, 1, 1+IMM2_SIZE,          /* Type *+, ++, ?+, upto+                 */
152    /* Character class & ref repeats                                         */    /* Character class & ref repeats                                         */
153    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */
154    0, 0,                          /* CRRANGE, CRMINRANGE                    */    0, 0,                          /* CRRANGE, CRMINRANGE                    */
# Line 182  remember the fact that a character could Line 187  remember the fact that a character could
187  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
188  two tables that follow must also be modified. */  two tables that follow must also be modified. */
189    
190  static const uschar poptable[] = {  static const pcre_uint8 poptable[] = {
191    0,                             /* End                                    */    0,                             /* End                                    */
192    0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */    0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */
193    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 249  static const uschar poptable[] = { Line 254  static const uschar poptable[] = {
254  /* 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,
255  and \w */  and \w */
256    
257  static const uschar toptable1[] = {  static const pcre_uint8 toptable1[] = {
258    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
259    ctype_digit, ctype_digit,    ctype_digit, ctype_digit,
260    ctype_space, ctype_space,    ctype_space, ctype_space,
# Line 257  static const uschar toptable1[] = { Line 262  static const uschar toptable1[] = {
262    0, 0                            /* OP_ANY, OP_ALLANY */    0, 0                            /* OP_ANY, OP_ALLANY */
263  };  };
264    
265  static const uschar toptable2[] = {  static const pcre_uint8 toptable2[] = {
266    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
267    ctype_digit, 0,    ctype_digit, 0,
268    ctype_space, 0,    ctype_space, 0,
# Line 296  Returns:       nothing Line 301  Returns:       nothing
301  */  */
302    
303  static void  static void
304  pchars(unsigned char *p, int length, FILE *f)  pchars(const pcre_uchar *p, int length, FILE *f)
305  {  {
306  int c;  int c;
307  while (length-- > 0)  while (length-- > 0)
# Line 386  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 398  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 409  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 442  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 470  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 542  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 556  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 567  for (;;) Line 573  for (;;)
573    int clen, dlen;    int clen, dlen;
574    unsigned int c, d;    unsigned int 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. */
582    
# Line 583  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 604  for (;;) Line 612  for (;;)
612    if (ptr < end_subject)    if (ptr < end_subject)
613      {      {
614      clen = 1;        /* Number of bytes in the character */      clen = 1;        /* Number of bytes in the character */
615  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
616      if (utf8) { GETCHARLEN(c, ptr, clen); } else      if (utf) { GETCHARLEN(c, ptr, clen); } else
617  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
618      c = *ptr;      c = *ptr;
619      }      }
620    else    else
# Line 624  for (;;) Line 632  for (;;)
632      {      {
633      stateblock *current_state = active_states + i;      stateblock *current_state = active_states + i;
634      BOOL caseless = FALSE;      BOOL caseless = FALSE;
635      const uschar *code;      const pcre_uchar *code;
636      int state_offset = current_state->offset;      int state_offset = current_state->offset;
637      int count, codevalue, rrc;      int count, codevalue, rrc;
638    
# Line 637  for (;;) Line 645  for (;;)
645    
646      /* 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
647      (negated) state until the number of characters in the data field have      (negated) state until the number of characters in the data field have
648      been skipped". */      been skipped". If the could_continue flag was passed over from a previous
649        state, arrange for it to passed on. */
650    
651      if (state_offset < 0)      if (state_offset < 0)
652        {        {
# Line 646  for (;;) Line 655  for (;;)
655          DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));          DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
656          ADD_NEW_DATA(state_offset, current_state->count,          ADD_NEW_DATA(state_offset, current_state->count,
657            current_state->data - 1);            current_state->data - 1);
658            if (could_continue) reset_could_continue = TRUE;
659          continue;          continue;
660          }          }
661        else        else
# Line 693  for (;;) Line 703  for (;;)
703      if (coptable[codevalue] > 0)      if (coptable[codevalue] > 0)
704        {        {
705        dlen = 1;        dlen = 1;
706  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
707        if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else        if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
708  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
709        d = code[coptable[codevalue]];        d = code[coptable[codevalue]];
710        if (codevalue >= OP_TYPESTAR)        if (codevalue >= OP_TYPESTAR)
711          {          {
# Line 816  for (;;) Line 826  for (;;)
826        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
827        case OP_CBRA:        case OP_CBRA:
828        case OP_SCBRA:        case OP_SCBRA:
829        ADD_ACTIVE((int)(code - start_code + 3 + LINK_SIZE),  0);        ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE),  0);
830        code += GET(code, 1);        code += GET(code, 1);
831        while (*code == OP_ALT)        while (*code == OP_ALT)
832          {          {
# Line 884  for (;;) Line 894  for (;;)
894        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
895        case OP_ANY:        case OP_ANY:
896        if (clen > 0 && !IS_NEWLINE(ptr))        if (clen > 0 && !IS_NEWLINE(ptr))
897          { ADD_NEW(state_offset + 1, 0); }          {
898            if (ptr + 1 >= md->end_subject &&
899                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
900                NLBLOCK->nltype == NLTYPE_FIXED &&
901                NLBLOCK->nllen == 2 &&
902                c == NLBLOCK->nl[0])
903              {
904              could_continue = partial_newline = TRUE;
905              }
906            else
907              {
908              ADD_NEW(state_offset + 1, 0);
909              }
910            }
911        break;        break;
912    
913        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
# Line 912  for (;;) Line 935  for (;;)
935                 (ptr == end_subject - md->nllen)                 (ptr == end_subject - md->nllen)
936              ))              ))
937            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
938            else if (ptr + 1 >= md->end_subject &&
939                     (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
940                     NLBLOCK->nltype == NLTYPE_FIXED &&
941                     NLBLOCK->nllen == 2 &&
942                     c == NLBLOCK->nl[0])
943              {
944              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
945                {
946                reset_could_continue = TRUE;
947                ADD_NEW_DATA(-(state_offset + 1), 0, 1);
948                }
949              else could_continue = partial_newline = TRUE;
950              }
951          }          }
952        break;        break;
953    
# Line 924  for (;;) Line 960  for (;;)
960          else if (clen == 0 ||          else if (clen == 0 ||
961              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
962            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
963            else if (ptr + 1 >= md->end_subject &&
964                     (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
965                     NLBLOCK->nltype == NLTYPE_FIXED &&
966                     NLBLOCK->nllen == 2 &&
967                     c == NLBLOCK->nl[0])
968              {
969              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
970                {
971                reset_could_continue = TRUE;
972                ADD_NEW_DATA(-(state_offset + 1), 0, 1);
973                }
974              else could_continue = partial_newline = TRUE;
975              }
976          }          }
977        else if (IS_NEWLINE(ptr))        else if (IS_NEWLINE(ptr))
978          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
# Line 956  for (;;) Line 1005  for (;;)
1005    
1006          if (ptr > start_subject)          if (ptr > start_subject)
1007            {            {
1008            const uschar *temp = ptr - 1;            const pcre_uchar *temp = ptr - 1;
1009            if (temp < md->start_used_ptr) md->start_used_ptr = temp;            if (temp < md->start_used_ptr) md->start_used_ptr = temp;
1010  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
1011            if (utf8) BACKCHAR(temp);            if (utf) { BACKCHAR(temp); }
1012  #endif  #endif
1013            GETCHARTEST(d, temp);            GETCHARTEST(d, temp);
1014  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
# Line 1024  for (;;) Line 1073  for (;;)
1073            break;            break;
1074    
1075            case PT_GC:            case PT_GC:
1076            OK = _pcre_ucp_gentype[prop->chartype] == code[2];            OK = PRIV(ucp_gentype)[prop->chartype] == code[2];
1077            break;            break;
1078    
1079            case PT_PC:            case PT_PC:
# Line 1038  for (;;) Line 1087  for (;;)
1087            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1088    
1089            case PT_ALNUM:            case PT_ALNUM:
1090            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1091                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1092            break;            break;
1093    
1094            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1095            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1096                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1097            break;            break;
1098    
1099            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1100            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1101                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1102                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1103            break;            break;
1104    
1105            case PT_WORD:            case PT_WORD:
1106            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1107                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1108                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1109            break;            break;
1110    
# Line 1086  for (;;) Line 1135  for (;;)
1135        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1136        if (clen > 0)        if (clen > 0)
1137          {          {
1138          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1139                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1140                NLBLOCK->nltype == NLTYPE_FIXED &&
1141                NLBLOCK->nllen == 2 &&
1142                c == NLBLOCK->nl[0])
1143              {
1144              could_continue = partial_newline = TRUE;
1145              }
1146            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1147              (c < 256 &&              (c < 256 &&
1148                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1149                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1109  for (;;) Line 1166  for (;;)
1166        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
1167        if (clen > 0)        if (clen > 0)
1168          {          {
1169          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1170                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1171                NLBLOCK->nltype == NLTYPE_FIXED &&
1172                NLBLOCK->nllen == 2 &&
1173                c == NLBLOCK->nl[0])
1174              {
1175              could_continue = partial_newline = TRUE;
1176              }
1177            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1178              (c < 256 &&              (c < 256 &&
1179                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1180                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1131  for (;;) Line 1196  for (;;)
1196        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
1197        if (clen > 0)        if (clen > 0)
1198          {          {
1199          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1200                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1201                NLBLOCK->nltype == NLTYPE_FIXED &&
1202                NLBLOCK->nllen == 2 &&
1203                c == NLBLOCK->nl[0])
1204              {
1205              could_continue = partial_newline = TRUE;
1206              }
1207            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1208              (c < 256 &&              (c < 256 &&
1209                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1210                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1151  for (;;) Line 1224  for (;;)
1224        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1225        if (clen > 0)        if (clen > 0)
1226          {          {
1227          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1228                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1229                NLBLOCK->nltype == NLTYPE_FIXED &&
1230                NLBLOCK->nllen == 2 &&
1231                c == NLBLOCK->nl[0])
1232              {
1233              could_continue = partial_newline = TRUE;
1234              }
1235            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1236              (c < 256 &&              (c < 256 &&
1237                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1238                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
1239            {            {
1240            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1241              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); }
1242            else            else
1243              { ADD_NEW(state_offset, count); }              { ADD_NEW(state_offset, count); }
1244            }            }
# Line 1168  for (;;) Line 1249  for (;;)
1249        case OP_TYPEUPTO:        case OP_TYPEUPTO:
1250        case OP_TYPEMINUPTO:        case OP_TYPEMINUPTO:
1251        case OP_TYPEPOSUPTO:        case OP_TYPEPOSUPTO:
1252        ADD_ACTIVE(state_offset + 4, 0);        ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0);
1253        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1254        if (clen > 0)        if (clen > 0)
1255          {          {
1256          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1257                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1258                NLBLOCK->nltype == NLTYPE_FIXED &&
1259                NLBLOCK->nllen == 2 &&
1260                c == NLBLOCK->nl[0])
1261              {
1262              could_continue = partial_newline = TRUE;
1263              }
1264            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1265              (c < 256 &&              (c < 256 &&
1266                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1267                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1183  for (;;) Line 1272  for (;;)
1272              next_active_state--;              next_active_state--;
1273              }              }
1274            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1275              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); }
1276            else            else
1277              { ADD_NEW(state_offset, count); }              { ADD_NEW(state_offset, count); }
1278            }            }
# Line 1218  for (;;) Line 1307  for (;;)
1307            break;            break;
1308    
1309            case PT_GC:            case PT_GC:
1310            OK = _pcre_ucp_gentype[prop->chartype] == code[3];            OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
1311            break;            break;
1312    
1313            case PT_PC:            case PT_PC:
# Line 1232  for (;;) Line 1321  for (;;)
1321            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1322    
1323            case PT_ALNUM:            case PT_ALNUM:
1324            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1325                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1326            break;            break;
1327    
1328            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1329            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1330                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1331            break;            break;
1332    
1333            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1334            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1335                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1336                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1337            break;            break;
1338    
1339            case PT_WORD:            case PT_WORD:
1340            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1341                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1342                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1343            break;            break;
1344    
# Line 1281  for (;;) Line 1370  for (;;)
1370        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1371        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1372          {          {
1373          const uschar *nptr = ptr + clen;          const pcre_uchar *nptr = ptr + clen;
1374          int ncount = 0;          int ncount = 0;
1375          if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)          if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
1376            {            {
# Line 1465  for (;;) Line 1554  for (;;)
1554            break;            break;
1555    
1556            case PT_GC:            case PT_GC:
1557            OK = _pcre_ucp_gentype[prop->chartype] == code[3];            OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
1558            break;            break;
1559    
1560            case PT_PC:            case PT_PC:
# Line 1479  for (;;) Line 1568  for (;;)
1568            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1569    
1570            case PT_ALNUM:            case PT_ALNUM:
1571            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1572                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1573            break;            break;
1574    
1575            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1576            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1577                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1578            break;            break;
1579    
1580            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1581            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1582                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1583                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1584            break;            break;
1585    
1586            case PT_WORD:            case PT_WORD:
1587            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1588                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1589                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1590            break;            break;
1591    
# Line 1537  for (;;) Line 1626  for (;;)
1626        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
1627        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1628          {          {
1629          const uschar *nptr = ptr + clen;          const pcre_uchar *nptr = ptr + clen;
1630          int ncount = 0;          int ncount = 0;
1631          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
1632              codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)              codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
# Line 1719  for (;;) Line 1808  for (;;)
1808        case OP_PROP_EXTRA + OP_TYPEMINUPTO:        case OP_PROP_EXTRA + OP_TYPEMINUPTO:
1809        case OP_PROP_EXTRA + OP_TYPEPOSUPTO:        case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
1810        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
1811          { ADD_ACTIVE(state_offset + 6, 0); }          { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); }
1812        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1813        if (clen > 0)        if (clen > 0)
1814          {          {
1815          BOOL OK;          BOOL OK;
1816          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1817          switch(code[4])          switch(code[1 + IMM2_SIZE + 1])
1818            {            {
1819            case PT_ANY:            case PT_ANY:
1820            OK = TRUE;            OK = TRUE;
# Line 1737  for (;;) Line 1826  for (;;)
1826            break;            break;
1827    
1828            case PT_GC:            case PT_GC:
1829            OK = _pcre_ucp_gentype[prop->chartype] == code[5];            OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2];
1830            break;            break;
1831    
1832            case PT_PC:            case PT_PC:
1833            OK = prop->chartype == code[5];            OK = prop->chartype == code[1 + IMM2_SIZE + 2];
1834            break;            break;
1835    
1836            case PT_SC:            case PT_SC:
1837            OK = prop->script == code[5];            OK = prop->script == code[1 + IMM2_SIZE + 2];
1838            break;            break;
1839    
1840            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1841    
1842            case PT_ALNUM:            case PT_ALNUM:
1843            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1844                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1845            break;            break;
1846    
1847            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1848            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1849                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1850            break;            break;
1851    
1852            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1853            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1854                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1855                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1856            break;            break;
1857    
1858            case PT_WORD:            case PT_WORD:
1859            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1860                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1861                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1862            break;            break;
1863    
# Line 1787  for (;;) Line 1876  for (;;)
1876              next_active_state--;              next_active_state--;
1877              }              }
1878            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1879              { ADD_NEW(state_offset + 6, 0); }              { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); }
1880            else            else
1881              { ADD_NEW(state_offset, count); }              { ADD_NEW(state_offset, count); }
1882            }            }
# Line 1800  for (;;) Line 1889  for (;;)
1889        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
1890        case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
1891        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
1892          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1893        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1894        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1895          {          {
1896          const uschar *nptr = ptr + clen;          const pcre_uchar *nptr = ptr + clen;
1897          int ncount = 0;          int ncount = 0;
1898          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
1899            {            {
# Line 1820  for (;;) Line 1909  for (;;)
1909            ncount++;            ncount++;
1910            nptr += ndlen;            nptr += ndlen;
1911            }            }
1912            if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
1913                reset_could_continue = TRUE;
1914          if (++count >= GET2(code, 1))          if (++count >= GET2(code, 1))
1915            { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }            { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
1916          else          else
1917            { ADD_NEW_DATA(-state_offset, count, ncount); }            { ADD_NEW_DATA(-state_offset, count, ncount); }
1918          }          }
# Line 1834  for (;;) Line 1925  for (;;)
1925        case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:        case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
1926        case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:        case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
1927        if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
1928          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1929        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1930        if (clen > 0)        if (clen > 0)
1931          {          {
# Line 1861  for (;;) Line 1952  for (;;)
1952              next_active_state--;              next_active_state--;
1953              }              }
1954            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1955              { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
1956            else            else
1957              { ADD_NEW_DATA(-state_offset, count, ncount); }              { ADD_NEW_DATA(-state_offset, count, ncount); }
1958            break;            break;
# Line 1878  for (;;) Line 1969  for (;;)
1969        case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:        case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
1970        case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:        case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
1971        if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
1972          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1973        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1974        if (clen > 0)        if (clen > 0)
1975          {          {
# Line 1907  for (;;) Line 1998  for (;;)
1998              next_active_state--;              next_active_state--;
1999              }              }
2000            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2001              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
2002            else            else
2003              { ADD_NEW_DATA(-state_offset, count, 0); }              { ADD_NEW_DATA(-state_offset, count, 0); }
2004            }            }
# Line 1920  for (;;) Line 2011  for (;;)
2011        case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:        case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
2012        case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:        case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
2013        if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
2014          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
2015        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2016        if (clen > 0)        if (clen > 0)
2017          {          {
# Line 1962  for (;;) Line 2053  for (;;)
2053              next_active_state--;              next_active_state--;
2054              }              }
2055            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2056              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
2057            else            else
2058              { ADD_NEW_DATA(-state_offset, count, 0); }              { ADD_NEW_DATA(-state_offset, count, 0); }
2059            }            }
# Line 1984  for (;;) Line 2075  for (;;)
2075        case OP_CHARI:        case OP_CHARI:
2076        if (clen == 0) break;        if (clen == 0) break;
2077    
2078  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2079        if (utf8)        if (utf)
2080          {          {
2081          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
2082            {            {
2083            unsigned int othercase;            unsigned int othercase;
2084            if (c < 128) othercase = fcc[c]; else            if (c < 128)
2085                othercase = fcc[c];
2086            /* If we have Unicode property support, we can use it to test the            else
2087            other case of the character. */              /* If we have Unicode property support, we can use it to test the
2088                other case of the character. */
2089  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2090            othercase = UCD_OTHERCASE(c);              othercase = UCD_OTHERCASE(c);
2091  #else  #else
2092            othercase = NOTACHAR;              othercase = NOTACHAR;
2093  #endif  #endif
2094    
2095            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
2096            }            }
2097          }          }
2098        else        else
2099  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2100          /* Not UTF mode */
       /* Non-UTF-8 mode */  
2101          {          {
2102          if (lcc[c] == lcc[d]) { ADD_NEW(state_offset + 2, 0); }          if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
2103              { ADD_NEW(state_offset + 2, 0); }
2104          }          }
2105        break;        break;
2106    
# Line 2023  for (;;) Line 2114  for (;;)
2114        case OP_EXTUNI:        case OP_EXTUNI:
2115        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
2116          {          {
2117          const uschar *nptr = ptr + clen;          const pcre_uchar *nptr = ptr + clen;
2118          int ncount = 0;          int ncount = 0;
2119          while (nptr < end_subject)          while (nptr < end_subject)
2120            {            {
# Line 2033  for (;;) Line 2124  for (;;)
2124            ncount++;            ncount++;
2125            nptr += nclen;            nptr += nclen;
2126            }            }
2127            if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
2128                reset_could_continue = TRUE;
2129          ADD_NEW_DATA(-(state_offset + 1), 0, ncount);          ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
2130          }          }
2131        break;        break;
# Line 2058  for (;;) Line 2151  for (;;)
2151          break;          break;
2152    
2153          case 0x000d:          case 0x000d:
2154          if (ptr + 1 < end_subject && ptr[1] == 0x0a)          if (ptr + 1 >= end_subject)
2155              {
2156              ADD_NEW(state_offset + 1, 0);
2157              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
2158                reset_could_continue = TRUE;
2159              }
2160            else if (ptr[1] == 0x0a)
2161            {            {
2162            ADD_NEW_DATA(-(state_offset + 1), 0, 1);            ADD_NEW_DATA(-(state_offset + 1), 0, 1);
2163            }            }
2164          else          else
2165            {            {
2166            ADD_NEW(state_offset + 1, 0);            ADD_NEW(state_offset + 1, 0);
2167            }            }
2168          break;          break;
2169          }          }
2170        break;        break;
# Line 2209  for (;;) Line 2308  for (;;)
2308          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2309          if (caseless)          if (caseless)
2310            {            {
2311  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2312            if (utf8 && d >= 128)            if (utf && d >= 128)
2313              {              {
2314  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2315              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2316  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2317              }              }
2318            else            else
2319  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2320            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2321            }            }
2322          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2323            {            {
# Line 2256  for (;;) Line 2355  for (;;)
2355          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2356          if (caseless)          if (caseless)
2357            {            {
2358  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2359            if (utf8 && d >= 128)            if (utf && d >= 128)
2360              {              {
2361  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2362              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2363  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2364              }              }
2365            else            else
2366  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2367            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2368            }            }
2369          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2370            {            {
# Line 2301  for (;;) Line 2400  for (;;)
2400          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2401          if (caseless)          if (caseless)
2402            {            {
2403  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2404            if (utf8 && d >= 128)            if (utf && d >= 128)
2405              {              {
2406  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2407              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2408  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2409              }              }
2410            else            else
2411  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2412            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2413            }            }
2414          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2415            {            {
# Line 2338  for (;;) Line 2437  for (;;)
2437          unsigned int otherd = NOTACHAR;          unsigned int 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            {            {
2453            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2454              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
2455            else            else
2456              { ADD_NEW(state_offset, count); }              { ADD_NEW(state_offset, count); }
2457            }            }
# Line 2375  for (;;) Line 2474  for (;;)
2474        case OP_NOTUPTO:        case OP_NOTUPTO:
2475        case OP_NOTMINUPTO:        case OP_NOTMINUPTO:
2476        case OP_NOTPOSUPTO:        case OP_NOTPOSUPTO:
2477        ADD_ACTIVE(state_offset + dlen + 3, 0);        ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0);
2478        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2479        if (clen > 0)        if (clen > 0)
2480          {          {
2481          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2482          if (caseless)          if (caseless)
2483            {            {
2484  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2485            if (utf8 && d >= 128)            if (utf && d >= 128)
2486              {              {
2487  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2488              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2489  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2490              }              }
2491            else            else
2492  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2493            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2494            }            }
2495          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2496            {            {
# Line 2401  for (;;) Line 2500  for (;;)
2500              next_active_state--;              next_active_state--;
2501              }              }
2502            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2503              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
2504            else            else
2505              { ADD_NEW(state_offset, count); }              { ADD_NEW(state_offset, count); }
2506            }            }
# Line 2418  for (;;) Line 2517  for (;;)
2517          {          {
2518          BOOL isinclass = FALSE;          BOOL isinclass = FALSE;
2519          int next_state_offset;          int next_state_offset;
2520          const uschar *ecode;          const pcre_uchar *ecode;
2521    
2522          /* 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
2523          can set isinclass from it. */          can set isinclass from it. */
2524    
2525          if (codevalue != OP_XCLASS)          if (codevalue != OP_XCLASS)
2526            {            {
2527            ecode = code + 33;            ecode = code + 1 + (32 / sizeof(pcre_uchar));
2528            if (clen > 0)            if (clen > 0)
2529              {              {
2530              isinclass = (c > 255)? (codevalue == OP_NCLASS) :              isinclass = (c > 255)? (codevalue == OP_NCLASS) :
2531                ((code[1 + c/8] & (1 << (c&7))) != 0);                ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0);
2532              }              }
2533            }            }
2534    
# Line 2440  for (;;) Line 2539  for (;;)
2539          else          else
2540           {           {
2541           ecode = code + GET(code, 1);           ecode = code + GET(code, 1);
2542           if (clen > 0) isinclass = _pcre_xclass(c, code + 1 + LINK_SIZE);           if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);
2543           }           }
2544    
2545          /* 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 2474  for (;;) Line 2573  for (;;)
2573            case OP_CRMINRANGE:            case OP_CRMINRANGE:
2574            count = current_state->count;  /* Already matched */            count = current_state->count;  /* Already matched */
2575            if (count >= GET2(ecode, 1))            if (count >= GET2(ecode, 1))
2576              { ADD_ACTIVE(next_state_offset + 5, 0); }              { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
2577            if (isinclass)            if (isinclass)
2578              {              {
2579              int max = GET2(ecode, 3);              int max = GET2(ecode, 1 + IMM2_SIZE);
2580              if (++count >= max && max != 0)   /* Max 0 => no limit */              if (++count >= max && max != 0)   /* Max 0 => no limit */
2581                { ADD_NEW(next_state_offset + 5, 0); }                { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
2582              else              else
2583                { ADD_NEW(state_offset, count); }                { ADD_NEW(state_offset, count); }
2584              }              }
# Line 2510  for (;;) Line 2609  for (;;)
2609          int rc;          int rc;
2610          int local_offsets[2];          int local_offsets[2];
2611          int local_workspace[1000];          int local_workspace[1000];
2612          const uschar *endasscode = code + GET(code, 1);          const pcre_uchar *endasscode = code + GET(code, 1);
2613    
2614          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
2615    
# Line 2547  for (;;) Line 2646  for (;;)
2646          if (code[LINK_SIZE+1] == OP_CALLOUT)          if (code[LINK_SIZE+1] == OP_CALLOUT)
2647            {            {
2648            rrc = 0;            rrc = 0;
2649            if (pcre_callout != NULL)            if (PUBL(callout) != NULL)
2650              {              {
2651              pcre_callout_block cb;              PUBL(callout_block) cb;
2652              cb.version          = 1;   /* Version 1 of the callout block */              cb.version          = 1;   /* Version 1 of the callout block */
2653              cb.callout_number   = code[LINK_SIZE+2];              cb.callout_number   = code[LINK_SIZE+2];
2654              cb.offset_vector    = offsets;              cb.offset_vector    = offsets;
2655    #ifdef COMPILE_PCRE8
2656              cb.subject          = (PCRE_SPTR)start_subject;              cb.subject          = (PCRE_SPTR)start_subject;
2657    #else
2658                cb.subject          = (PCRE_SPTR16)start_subject;
2659    #endif
2660              cb.subject_length   = (int)(end_subject - start_subject);              cb.subject_length   = (int)(end_subject - start_subject);
2661              cb.start_match      = (int)(current_subject - start_subject);              cb.start_match      = (int)(current_subject - start_subject);
2662              cb.current_position = (int)(ptr - start_subject);              cb.current_position = (int)(ptr - start_subject);
# Line 2563  for (;;) Line 2666  for (;;)
2666              cb.capture_last     = -1;              cb.capture_last     = -1;
2667              cb.callout_data     = md->callout_data;              cb.callout_data     = md->callout_data;
2668              cb.mark             = NULL;   /* No (*MARK) support */              cb.mark             = NULL;   /* No (*MARK) support */
2669              if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */              if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
2670              }              }
2671            if (rrc > 0) break;                      /* Fail this thread */            if (rrc > 0) break;                      /* Fail this thread */
2672            code += _pcre_OP_lengths[OP_CALLOUT];    /* Skip callout data */            code += PRIV(OP_lengths)[OP_CALLOUT];    /* Skip callout data */
2673            }            }
2674    
2675          condcode = code[LINK_SIZE+1];          condcode = code[LINK_SIZE+1];
# Line 2587  for (;;) Line 2690  for (;;)
2690    
2691          else if (condcode == OP_RREF || condcode == OP_NRREF)          else if (condcode == OP_RREF || condcode == OP_NRREF)
2692            {            {
2693            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE + 2);
2694            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
2695            if (md->recursive != NULL)            if (md->recursive != NULL)
2696              { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }              { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); }
2697            else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }            else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2698            }            }
2699    
# Line 2599  for (;;) Line 2702  for (;;)
2702          else          else
2703            {            {
2704            int rc;            int rc;
2705            const uschar *asscode = code + LINK_SIZE + 1;            const pcre_uchar *asscode = code + LINK_SIZE + 1;
2706            const uschar *endasscode = asscode + GET(asscode, 1);            const pcre_uchar *endasscode = asscode + GET(asscode, 1);
2707    
2708            while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);            while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
2709    
# Line 2631  for (;;) Line 2734  for (;;)
2734          dfa_recursion_info *ri;          dfa_recursion_info *ri;
2735          int local_offsets[1000];          int local_offsets[1000];
2736          int local_workspace[1000];          int local_workspace[1000];
2737          const uschar *callpat = start_code + GET(code, 1);          const pcre_uchar *callpat = start_code + GET(code, 1);
2738          int recno = (callpat == md->start_code)? 0 :          int recno = (callpat == md->start_code)? 0 :
2739            GET2(callpat, 1 + LINK_SIZE);            GET2(callpat, 1 + LINK_SIZE);
2740          int rc;          int rc;
# Line 2682  for (;;) Line 2785  for (;;)
2785            {            {
2786            for (rc = rc*2 - 2; rc >= 0; rc -= 2)            for (rc = rc*2 - 2; rc >= 0; rc -= 2)
2787              {              {
             const uschar *p = start_subject + local_offsets[rc];  
             const uschar *pp = start_subject + local_offsets[rc+1];  
2788              int charcount = local_offsets[rc+1] - local_offsets[rc];              int charcount = local_offsets[rc+1] - local_offsets[rc];
2789              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;  #ifdef SUPPORT_UTF
2790                const pcre_uchar *p = start_subject + local_offsets[rc];
2791                const pcre_uchar *pp = start_subject + local_offsets[rc+1];
2792                while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2793    #endif
2794              if (charcount > 0)              if (charcount > 0)
2795                {                {
2796                ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));                ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));
# Line 2708  for (;;) Line 2813  for (;;)
2813        case OP_BRAPOSZERO:        case OP_BRAPOSZERO:
2814          {          {
2815          int charcount, matched_count;          int charcount, matched_count;
2816          const uschar *local_ptr = ptr;          const pcre_uchar *local_ptr = ptr;
2817          BOOL allow_zero;          BOOL allow_zero;
2818    
2819          if (codevalue == OP_BRAPOSZERO)          if (codevalue == OP_BRAPOSZERO)
# Line 2758  for (;;) Line 2863  for (;;)
2863    
2864          if (matched_count > 0 || allow_zero)          if (matched_count > 0 || allow_zero)
2865            {            {
2866            const uschar *end_subpattern = code;            const pcre_uchar *end_subpattern = code;
2867            int next_state_offset;            int next_state_offset;
2868    
2869            do { end_subpattern += GET(end_subpattern, 1); }            do { end_subpattern += GET(end_subpattern, 1); }
# Line 2779  for (;;) Line 2884  for (;;)
2884              }              }
2885            else            else
2886              {              {
2887              const uschar *p = ptr;              const pcre_uchar *p = ptr;
2888              const uschar *pp = local_ptr;              const pcre_uchar *pp = local_ptr;
2889              charcount = pp - p;              charcount = (int)(pp - p);
2890              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;  #ifdef SUPPORT_UTF
2891                while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2892    #endif
2893              ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));              ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
2894              }              }
2895            }            }
# Line 2791  for (;;) Line 2898  for (;;)
2898    
2899        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2900        case OP_ONCE:        case OP_ONCE:
2901        case OP_ONCE_NC:        case OP_ONCE_NC:
2902          {          {
2903          int local_offsets[2];          int local_offsets[2];
2904          int local_workspace[1000];          int local_workspace[1000];
# Line 2809  for (;;) Line 2916  for (;;)
2916    
2917          if (rc >= 0)          if (rc >= 0)
2918            {            {
2919            const uschar *end_subpattern = code;            const pcre_uchar *end_subpattern = code;
2920            int charcount = local_offsets[1] - local_offsets[0];            int charcount = local_offsets[1] - local_offsets[0];
2921            int next_state_offset, repeat_state_offset;            int next_state_offset, repeat_state_offset;
2922    
# Line 2862  for (;;) Line 2969  for (;;)
2969              }              }
2970            else            else
2971              {              {
2972              const uschar *p = start_subject + local_offsets[0];  #ifdef SUPPORT_UTF
2973              const uschar *pp = start_subject + local_offsets[1];              const pcre_uchar *p = start_subject + local_offsets[0];
2974              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;              const pcre_uchar *pp = start_subject + local_offsets[1];
2975                while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2976    #endif
2977              ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));              ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
2978              if (repeat_state_offset >= 0)              if (repeat_state_offset >= 0)
2979                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
# Line 2880  for (;;) Line 2989  for (;;)
2989    
2990        case OP_CALLOUT:        case OP_CALLOUT:
2991        rrc = 0;        rrc = 0;
2992        if (pcre_callout != NULL)        if (PUBL(callout) != NULL)
2993          {          {
2994          pcre_callout_block cb;          PUBL(callout_block) cb;
2995          cb.version          = 1;   /* Version 1 of the callout block */          cb.version          = 1;   /* Version 1 of the callout block */
2996          cb.callout_number   = code[1];          cb.callout_number   = code[1];
2997          cb.offset_vector    = offsets;          cb.offset_vector    = offsets;
2998    #ifdef COMPILE_PCRE8
2999          cb.subject          = (PCRE_SPTR)start_subject;          cb.subject          = (PCRE_SPTR)start_subject;
3000    #else
3001            cb.subject          = (PCRE_SPTR16)start_subject;
3002    #endif
3003          cb.subject_length   = (int)(end_subject - start_subject);          cb.subject_length   = (int)(end_subject - start_subject);
3004          cb.start_match      = (int)(current_subject - start_subject);          cb.start_match      = (int)(current_subject - start_subject);
3005          cb.current_position = (int)(ptr - start_subject);          cb.current_position = (int)(ptr - start_subject);
# Line 2896  for (;;) Line 3009  for (;;)
3009          cb.capture_last     = -1;          cb.capture_last     = -1;
3010          cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
3011          cb.mark             = NULL;   /* No (*MARK) support */          cb.mark             = NULL;   /* No (*MARK) support */
3012          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */          if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
3013          }          }
3014        if (rrc == 0)        if (rrc == 0)
3015          { ADD_ACTIVE(state_offset + _pcre_OP_lengths[OP_CALLOUT], 0); }          { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); }
3016        break;        break;
3017    
3018    
# Line 2924  for (;;) Line 3037  for (;;)
3037    
3038    The "could_continue" variable is true if a state could have continued but    The "could_continue" variable is true if a state could have continued but
3039    for the fact that the end of the subject was reached. */    for the fact that the end of the subject was reached. */
3040    
3041    if (new_count <= 0)    if (new_count <= 0)
3042      {      {
3043      if (rlevel == 1 &&                               /* Top level, and */      if (rlevel == 1 &&                               /* Top level, and */
3044          could_continue &&                            /* Some could go on */          could_continue &&                            /* Some could go on, and */
3045          forced_fail != workspace[1] &&               /* Not all forced fail & */          forced_fail != workspace[1] &&               /* Not all forced fail & */
3046          (                                            /* either... */          (                                            /* either... */
3047          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
# Line 2936  for (;;) Line 3049  for (;;)
3049          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
3050           match_count < 0)                            /* no matches */           match_count < 0)                            /* no matches */
3051          ) &&                                         /* And... */          ) &&                                         /* And... */
3052          ptr >= end_subject &&                  /* Reached end of subject */          (
3053          ptr > md->start_used_ptr)              /* Inspected non-empty string */          partial_newline ||                           /* Either partial NL */
3054              (                                          /* or ... */
3055              ptr >= end_subject &&                /* End of subject and */
3056              ptr > md->start_used_ptr)            /* Inspected non-empty string */
3057              )
3058            )
3059        {        {
3060        if (offsetcount >= 2)        if (offsetcount >= 2)
3061          {          {
# Line 2996  Returns:          > 0 => number of match Line 3114  Returns:          > 0 => number of match
3114                   < -1 => some kind of unexpected problem                   < -1 => some kind of unexpected problem
3115  */  */
3116    
3117    #ifdef COMPILE_PCRE8
3118  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3119  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
3120    const char *subject, int length, int start_offset, int options, int *offsets,    const char *subject, int length, int start_offset, int options, int *offsets,
3121    int offsetcount, int *workspace, int wscount)    int offsetcount, int *workspace, int wscount)
3122    #else
3123    PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3124    pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
3125      PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
3126      int offsetcount, int *workspace, int wscount)
3127    #endif
3128  {  {
3129  real_pcre *re = (real_pcre *)argument_re;  REAL_PCRE *re = (REAL_PCRE *)argument_re;
3130  dfa_match_data match_block;  dfa_match_data match_block;
3131  dfa_match_data *md = &match_block;  dfa_match_data *md = &match_block;
3132  BOOL utf8, anchored, startline, firstline;  BOOL utf, anchored, startline, firstline;
3133  const uschar *current_subject, *end_subject, *lcc;  const pcre_uchar *current_subject, *end_subject;
   
 pcre_study_data internal_study;  
3134  const pcre_study_data *study = NULL;  const pcre_study_data *study = NULL;
 real_pcre internal_re;  
3135    
3136  const uschar *req_byte_ptr;  const pcre_uchar *req_char_ptr;
3137  const uschar *start_bits = NULL;  const pcre_uint8 *start_bits = NULL;
3138  BOOL first_byte_caseless = FALSE;  BOOL has_first_char = FALSE;
3139  BOOL req_byte_caseless = FALSE;  BOOL has_req_char = FALSE;
3140  int first_byte = -1;  pcre_uchar first_char = 0;
3141  int req_byte = -1;  pcre_uchar first_char2 = 0;
3142  int req_byte2 = -1;  pcre_uchar req_char = 0;
3143    pcre_uchar req_char2 = 0;
3144  int newline;  int newline;
3145    
3146  /* Plausibility checks */  /* Plausibility checks */
# Line 3052  if (extra_data != NULL) Line 3175  if (extra_data != NULL)
3175    }    }
3176    
3177  /* Check that the first field in the block is the magic number. If it is not,  /* Check that the first field in the block is the magic number. If it is not,
3178  test for a regex that was compiled on a host of opposite endianness. If this is  return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
3179  the case, flipped values are put in internal_re and internal_study if there was  REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
3180  study data too. */  means that the pattern is likely compiled with different endianness. */
3181    
3182  if (re->magic_number != MAGIC_NUMBER)  if (re->magic_number != MAGIC_NUMBER)
3183    {    return re->magic_number == REVERSED_MAGIC_NUMBER?
3184    re = _pcre_try_flipped(re, &internal_re, study, &internal_study);      PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
3185    if (re == NULL) return PCRE_ERROR_BADMAGIC;  if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
   if (study != NULL) study = &internal_study;  
   }  
3186    
3187  /* Set some local values */  /* Set some local values */
3188    
3189  current_subject = (const unsigned char *)subject + start_offset;  current_subject = (const pcre_uchar *)subject + start_offset;
3190  end_subject = (const unsigned char *)subject + length;  end_subject = (const pcre_uchar *)subject + length;
3191  req_byte_ptr = current_subject - 1;  req_char_ptr = current_subject - 1;
3192    
3193  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3194  utf8 = (re->options & PCRE_UTF8) != 0;  /* PCRE_UTF16 has the same value as PCRE_UTF8. */
3195    utf = (re->options & PCRE_UTF8) != 0;
3196  #else  #else
3197  utf8 = FALSE;  utf = FALSE;
3198  #endif  #endif
3199    
3200  anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||  anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
# Line 3080  anchored = (options & (PCRE_ANCHORED|PCR Line 3202  anchored = (options & (PCRE_ANCHORED|PCR
3202    
3203  /* The remaining fixed data for passing around. */  /* The remaining fixed data for passing around. */
3204    
3205  md->start_code = (const uschar *)argument_re +  md->start_code = (const pcre_uchar *)argument_re +
3206      re->name_table_offset + re->name_count * re->name_entry_size;      re->name_table_offset + re->name_count * re->name_entry_size;
3207  md->start_subject = (const unsigned char *)subject;  md->start_subject = (const pcre_uchar *)subject;
3208  md->end_subject = end_subject;  md->end_subject = end_subject;
3209  md->start_offset = start_offset;  md->start_offset = start_offset;
3210  md->moptions = options;  md->moptions = options;
# Line 3143  else Line 3265  else
3265  /* 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
3266  back the character offset. */  back the character offset. */
3267    
3268  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3269  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)  if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
3270    {    {
3271    int erroroffset;    int erroroffset;
3272    int errorcode = _pcre_valid_utf8((uschar *)subject, length, &erroroffset);    int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset);
3273    if (errorcode != 0)    if (errorcode != 0)
3274      {      {
3275      if (offsetcount >= 2)      if (offsetcount >= 2)
# Line 3159  if (utf8 && (options & PCRE_NO_UTF8_CHEC Line 3281  if (utf8 && (options & PCRE_NO_UTF8_CHEC
3281        PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;        PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
3282      }      }
3283    if (start_offset > 0 && start_offset < length &&    if (start_offset > 0 && start_offset < length &&
3284          (((USPTR)subject)[start_offset] & 0xc0) == 0x80)          NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
3285      return PCRE_ERROR_BADUTF8_OFFSET;      return PCRE_ERROR_BADUTF8_OFFSET;
3286    }    }
3287  #endif  #endif
# Line 3168  if (utf8 && (options & PCRE_NO_UTF8_CHEC Line 3290  if (utf8 && (options & PCRE_NO_UTF8_CHEC
3290  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
3291  in other programs later. */  in other programs later. */
3292    
3293  if (md->tables == NULL) md->tables = _pcre_default_tables;  if (md->tables == NULL) md->tables = PRIV(default_tables);
3294    
3295  /* 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
3296  used in a loop when finding where to start. */  where to start. */
3297    
 lcc = md->tables + lcc_offset;  
3298  startline = (re->flags & PCRE_STARTLINE) != 0;  startline = (re->flags & PCRE_STARTLINE) != 0;
3299  firstline = (re->options & PCRE_FIRSTLINE) != 0;  firstline = (re->options & PCRE_FIRSTLINE) != 0;
3300    
# Line 3187  if (!anchored) Line 3308  if (!anchored)
3308    {    {
3309    if ((re->flags & PCRE_FIRSTSET) != 0)    if ((re->flags & PCRE_FIRSTSET) != 0)
3310      {      {
3311      first_byte = re->first_byte & 255;      has_first_char = TRUE;
3312      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)      first_char = first_char2 = (pcre_uchar)(re->first_char);
3313        first_byte = lcc[first_byte];      if ((re->flags & PCRE_FCH_CASELESS) != 0)
3314          {
3315          first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char);
3316    #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
3317          if (utf && first_char > 127)
3318            first_char2 = UCD_OTHERCASE(first_char);
3319    #endif
3320          }
3321      }      }
3322    else    else
3323      {      {
# Line 3204  character" set. */ Line 3332  character" set. */
3332    
3333  if ((re->flags & PCRE_REQCHSET) != 0)  if ((re->flags & PCRE_REQCHSET) != 0)
3334    {    {
3335    req_byte = re->req_byte & 255;    has_req_char = TRUE;
3336    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;    req_char = req_char2 = (pcre_uchar)(re->req_char);
3337    req_byte2 = (md->tables + fcc_offset)[req_byte];  /* case flipped */    if ((re->flags & PCRE_RCH_CASELESS) != 0)
3338        {
3339        req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char);
3340    #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
3341        if (utf && req_char > 127)
3342          req_char2 = UCD_OTHERCASE(req_char);
3343    #endif
3344        }
3345    }    }
3346    
3347  /* 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 3219  for (;;) Line 3354  for (;;)
3354    
3355    if ((options & PCRE_DFA_RESTART) == 0)    if ((options & PCRE_DFA_RESTART) == 0)
3356      {      {
3357      const uschar *save_end_subject = end_subject;      const pcre_uchar *save_end_subject = end_subject;
3358    
3359      /* 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
3360      line of a multiline string. Implement this by temporarily adjusting      line of a multiline string. Implement this by temporarily adjusting
# Line 3228  for (;;) Line 3363  for (;;)
3363    
3364      if (firstline)      if (firstline)
3365        {        {
3366        USPTR t = current_subject;        PCRE_PUCHAR t = current_subject;
3367  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3368        if (utf8)        if (utf)
3369          {          {
3370          while (t < md->end_subject && !IS_NEWLINE(t))          while (t < md->end_subject && !IS_NEWLINE(t))
3371            {            {
3372            t++;            t++;
3373            while (t < end_subject && (*t & 0xc0) == 0x80) t++;            ACROSSCHAR(t < end_subject, *t, t++);
3374            }            }
3375          }          }
3376        else        else
# Line 3252  for (;;) Line 3387  for (;;)
3387    
3388      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
3389        {        {
3390        /* Advance to a known first byte. */        /* Advance to a known first char. */
3391    
3392        if (first_byte >= 0)        if (has_first_char)
3393          {          {
3394          if (first_byte_caseless)          if (first_char != first_char2)
3395            while (current_subject < end_subject &&            while (current_subject < end_subject &&
3396                   lcc[*current_subject] != first_byte)                *current_subject != first_char && *current_subject != first_char2)
3397              current_subject++;              current_subject++;
3398          else          else
3399            while (current_subject < end_subject &&            while (current_subject < end_subject &&
3400                   *current_subject != first_byte)                   *current_subject != first_char)
3401              current_subject++;              current_subject++;
3402          }          }
3403    
# Line 3272  for (;;) Line 3407  for (;;)
3407          {          {
3408          if (current_subject > md->start_subject + start_offset)          if (current_subject > md->start_subject + start_offset)
3409            {            {
3410  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3411            if (utf8)            if (utf)
3412              {              {
3413              while (current_subject < end_subject &&              while (current_subject < end_subject &&
3414                     !WAS_NEWLINE(current_subject))                     !WAS_NEWLINE(current_subject))
3415                {                {
3416                current_subject++;                current_subject++;
3417                while(current_subject < end_subject &&                ACROSSCHAR(current_subject < end_subject, *current_subject,
3418                      (*current_subject & 0xc0) == 0x80)                  current_subject++);
                 current_subject++;  
3419                }                }
3420              }              }
3421            else            else
# Line 3308  for (;;) Line 3442  for (;;)
3442          while (current_subject < end_subject)          while (current_subject < end_subject)
3443            {            {
3444            register unsigned int c = *current_subject;            register unsigned int c = *current_subject;
3445    #ifndef COMPILE_PCRE8
3446              if (c > 255) c = 255;
3447    #endif
3448            if ((start_bits[c/8] & (1 << (c&7))) == 0)            if ((start_bits[c/8] & (1 << (c&7))) == 0)
3449              {              {
3450              current_subject++;              current_subject++;
3451  #ifdef SUPPORT_UTF8  #if defined SUPPORT_UTF && defined COMPILE_PCRE8
3452              if (utf8)              /* In non 8-bit mode, the iteration will stop for
3453                while(current_subject < end_subject &&              characters > 255 at the beginning or not stop at all. */
3454                      (*current_subject & 0xc0) == 0x80) current_subject++;              if (utf)
3455                  ACROSSCHAR(current_subject < end_subject, *current_subject,
3456                    current_subject++);
3457  #endif  #endif
3458              }              }
3459            else break;            else break;
# Line 3342  for (;;) Line 3481  for (;;)
3481            (pcre_uint32)(end_subject - current_subject) < study->minlength)            (pcre_uint32)(end_subject - current_subject) < study->minlength)
3482          return PCRE_ERROR_NOMATCH;          return PCRE_ERROR_NOMATCH;
3483    
3484        /* 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
3485        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
3486        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
3487        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
3488        nested unlimited repeats that aren't going to match. Writing separate        nested unlimited repeats that aren't going to match. Writing separate
# Line 3355  for (;;) Line 3494  for (;;)
3494        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
3495        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. */
3496    
3497        if (req_byte >= 0 && end_subject - current_subject < REQ_BYTE_MAX)        if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX)
3498          {          {
3499          register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);          register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0);
3500    
3501          /* 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
3502          place we found it at last time. */          place we found it at last time. */
3503    
3504          if (p > req_byte_ptr)          if (p > req_char_ptr)
3505            {            {
3506            if (req_byte_caseless)            if (req_char != req_char2)
3507              {              {
3508              while (p < end_subject)              while (p < end_subject)
3509                {                {
3510                register int pp = *p++;                register int pp = *p++;
3511                if (pp == req_byte || pp == req_byte2) { p--; break; }                if (pp == req_char || pp == req_char2) { p--; break; }
3512                }                }
3513              }              }
3514            else            else
3515              {              {
3516              while (p < end_subject)              while (p < end_subject)
3517                {                {
3518                if (*p++ == req_byte) { p--; break; }                if (*p++ == req_char) { p--; break; }
3519                }                }
3520              }              }
3521    
# Line 3389  for (;;) Line 3528  for (;;)
3528            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
3529            the start hasn't passed this character yet. */            the start hasn't passed this character yet. */
3530    
3531            req_byte_ptr = p;            req_char_ptr = p;
3532            }            }
3533          }          }
3534        }        }
# Line 3421  for (;;) Line 3560  for (;;)
3560    
3561    if (firstline && IS_NEWLINE(current_subject)) break;    if (firstline && IS_NEWLINE(current_subject)) break;
3562    current_subject++;    current_subject++;
3563    if (utf8)  #ifdef SUPPORT_UTF
3564      if (utf)
3565      {      {
3566      while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80)      ACROSSCHAR(current_subject < end_subject, *current_subject,
3567        current_subject++;        current_subject++);
3568      }      }
3569    #endif
3570    if (current_subject > end_subject) break;    if (current_subject > end_subject) break;
3571    
3572    /* 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

Legend:
Removed from v.728  
changed lines
  Added in v.919

  ViewVC Help
Powered by ViewVC 1.1.5