/[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 231 by ph10, Tue Sep 11 11:15:33 2007 UTC revision 439 by ph10, Tue Sep 8 17:27:24 2009 UTC
# Line 3  Line 3 
3  *************************************************/  *************************************************/
4    
5  /* PCRE is a library of functions to support regular expressions whose syntax  /* PCRE is a library of functions to support regular expressions whose syntax
6  and semantics are as close as possible to those of the Perl 5 language.  and semantics are as close as possible to those of the Perl 5 language (but see
7    below for why this module is different).
8    
9                         Written by Philip Hazel                         Written by Philip Hazel
10             Copyright (c) 1997-2007 University of Cambridge             Copyright (c) 1997-2009 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 44  FSM). This is NOT Perl- compatible, but Line 45  FSM). This is NOT Perl- compatible, but
45  applications. */  applications. */
46    
47    
48    /* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved
49    the performance of his patterns greatly. I could not use it as it stood, as it
50    was not thread safe, and made assumptions about pattern sizes. Also, it caused
51    test 7 to loop, and test 9 to crash with a segfault.
52    
53    The issue is the check for duplicate states, which is done by a simple linear
54    search up the state list. (Grep for "duplicate" below to find the code.) For
55    many patterns, there will never be many states active at one time, so a simple
56    linear search is fine. In patterns that have many active states, it might be a
57    bottleneck. The suggested code used an indexing scheme to remember which states
58    had previously been used for each character, and avoided the linear search when
59    it knew there was no chance of a duplicate. This was implemented when adding
60    states to the state lists.
61    
62    I wrote some thread-safe, not-limited code to try something similar at the time
63    of checking for duplicates (instead of when adding states), using index vectors
64    on the stack. It did give a 13% improvement with one specially constructed
65    pattern for certain subject strings, but on other strings and on many of the
66    simpler patterns in the test suite it did worse. The major problem, I think,
67    was the extra time to initialize the index. This had to be done for each call
68    of internal_dfa_exec(). (The supplied patch used a static vector, initialized
69    only once - I suspect this was the cause of the problems with the tests.)
70    
71    Overall, I concluded that the gains in some cases did not outweigh the losses
72    in others, so I abandoned this code. */
73    
74    
75    
76  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
77  #include <config.h>  #include "config.h"
78  #endif  #endif
79    
80  #define NLBLOCK md             /* Block containing newline information */  #define NLBLOCK md             /* Block containing newline information */
# Line 60  applications. */ Line 89  applications. */
89  #define SP "                   "  #define SP "                   "
90    
91    
   
92  /*************************************************  /*************************************************
93  *      Code parameters and static tables         *  *      Code parameters and static tables         *
94  *************************************************/  *************************************************/
# Line 84  centralize the loading of these characte Line 112  centralize the loading of these characte
112  small value. ***NOTE*** If the start of this table is modified, the two tables  small value. ***NOTE*** If the start of this table is modified, the two tables
113  that follow must also be modified. */  that follow must also be modified. */
114    
115  static uschar coptable[] = {  static const uschar 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                 */
119    0, 0,                          /* Any, Anybyte                           */    0, 0, 0,                       /* Any, AllAny, Anybyte                   */
120    0, 0, 0,                       /* NOTPROP, PROP, EXTUNI                  */    0, 0, 0,                       /* NOTPROP, PROP, EXTUNI                  */
121    0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */    0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
122    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */
# Line 132  static uschar coptable[] = { Line 160  static uschar coptable[] = {
160    0,                             /* DEF                                    */    0,                             /* DEF                                    */
161    0, 0,                          /* BRAZERO, BRAMINZERO                    */    0, 0,                          /* BRAZERO, BRAMINZERO                    */
162    0, 0, 0, 0,                    /* PRUNE, SKIP, THEN, COMMIT              */    0, 0, 0, 0,                    /* PRUNE, SKIP, THEN, COMMIT              */
163    0, 0                           /* FAIL, ACCEPT                           */    0, 0, 0                        /* FAIL, ACCEPT, SKIPZERO                 */
164  };  };
165    
166  /* 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,
167  and \w */  and \w */
168    
169  static uschar toptable1[] = {  static const uschar toptable1[] = {
170    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
171    ctype_digit, ctype_digit,    ctype_digit, ctype_digit,
172    ctype_space, ctype_space,    ctype_space, ctype_space,
173    ctype_word,  ctype_word,    ctype_word,  ctype_word,
174    0                               /* OP_ANY */    0, 0                            /* OP_ANY, OP_ALLANY */
175  };  };
176    
177  static uschar toptable2[] = {  static const uschar toptable2[] = {
178    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
179    ctype_digit, 0,    ctype_digit, 0,
180    ctype_space, 0,    ctype_space, 0,
181    ctype_word,  0,    ctype_word,  0,
182    1                               /* OP_ANY */    1, 1                            /* OP_ANY, OP_ALLANY */
183  };  };
184    
185    
# Line 223  Arguments: Line 251  Arguments:
251    rlevel            function call recursion level    rlevel            function call recursion level
252    recursing         regex recursive call level    recursing         regex recursive call level
253    
254  Returns:            > 0 =>  Returns:            > 0 => number of match offset pairs placed in offsets
255                      = 0 =>                      = 0 => offsets overflowed; longest matches are present
256                       -1 => failed to match                       -1 => failed to match
257                     < -1 => some kind of unexpected problem                     < -1 => some kind of unexpected problem
258    
# Line 389  if (*first_op == OP_REVERSE) Line 417  if (*first_op == OP_REVERSE)
417        current_subject - start_subject : max_back;        current_subject - start_subject : max_back;
418      current_subject -= gone_back;      current_subject -= gone_back;
419      }      }
420    
421      /* Save the earliest consulted character */
422    
423      if (current_subject < md->start_used_ptr)
424        md->start_used_ptr = current_subject;
425    
426    /* Now we can process the individual branches. */    /* Now we can process the individual branches. */
427    
# Line 454  for (;;) Line 487  for (;;)
487    int i, j;    int i, j;
488    int clen, dlen;    int clen, dlen;
489    unsigned int c, d;    unsigned int c, d;
490      int forced_fail = 0;
491      int reached_end = 0;
492    
493    /* 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
494    new state list. */    new state list. */
# Line 511  for (;;) Line 546  for (;;)
546      stateblock *current_state = active_states + i;      stateblock *current_state = active_states + i;
547      const uschar *code;      const uschar *code;
548      int state_offset = current_state->offset;      int state_offset = current_state->offset;
549      int count, codevalue;      int count, codevalue, rrc;
 #ifdef SUPPORT_UCP  
     int chartype, script;  
 #endif  
550    
551  #ifdef DEBUG  #ifdef DEBUG
552      printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);      printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);
# Line 546  for (;;) Line 578  for (;;)
578          }          }
579        }        }
580    
581      /* Check for a duplicate state with the same count, and skip if found. */      /* Check for a duplicate state with the same count, and skip if found.
582        See the note at the head of this module about the possibility of improving
583        performance here. */
584    
585      for (j = 0; j < i; j++)      for (j = 0; j < i; j++)
586        {        {
# Line 627  for (;;) Line 661  for (;;)
661            ADD_ACTIVE(state_offset - GET(code, 1), 0);            ADD_ACTIVE(state_offset - GET(code, 1), 0);
662            }            }
663          }          }
664        else if (ptr > current_subject || (md->moptions & PCRE_NOTEMPTY) == 0)        else
665          {          {
666          if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;          reached_end++;    /* Count branches that reach the end */
667            else if (match_count > 0 && ++match_count * 2 >= offsetcount)          if (ptr > current_subject || (md->moptions & PCRE_NOTEMPTY) == 0)
668              match_count = 0;            {
669          count = ((match_count == 0)? offsetcount : match_count * 2) - 2;            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
670          if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));              else if (match_count > 0 && ++match_count * 2 >= offsetcount)
671          if (offsetcount >= 2)                match_count = 0;
672            {            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
673            offsets[0] = current_subject - start_subject;            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
674            offsets[1] = ptr - start_subject;            if (offsetcount >= 2)
675            DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,              {
676              offsets[1] - offsets[0], current_subject));              offsets[0] = current_subject - start_subject;
677            }              offsets[1] = ptr - start_subject;
678          if ((md->moptions & PCRE_DFA_SHORTEST) != 0)              DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
679            {                offsets[1] - offsets[0], current_subject));
680            DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"              }
681              "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,            if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
682              match_count, rlevel*2-2, SP));              {
683            return match_count;              DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
684            }                "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,
685                  match_count, rlevel*2-2, SP));
686                return match_count;
687                }
688              }
689          }          }
690        break;        break;
691    
# Line 694  for (;;) Line 732  for (;;)
732        break;        break;
733    
734        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
735          case OP_SKIPZERO:
736          code += 1 + GET(code, 2);
737          while (*code == OP_ALT) code += GET(code, 1);
738          ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
739          break;
740    
741          /*-----------------------------------------------------------------*/
742        case OP_CIRC:        case OP_CIRC:
743        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
744            ((ims & PCRE_MULTILINE) != 0 &&            ((ims & PCRE_MULTILINE) != 0 &&
# Line 732  for (;;) Line 777  for (;;)
777    
778        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
779        case OP_ANY:        case OP_ANY:
780        if (clen > 0 && ((ims & PCRE_DOTALL) != 0 || !IS_NEWLINE(ptr)))        if (clen > 0 && !IS_NEWLINE(ptr))
781            { ADD_NEW(state_offset + 1, 0); }
782          break;
783    
784          /*-----------------------------------------------------------------*/
785          case OP_ALLANY:
786          if (clen > 0)
787          { ADD_NEW(state_offset + 1, 0); }          { ADD_NEW(state_offset + 1, 0); }
788        break;        break;
789    
# Line 747  for (;;) Line 798  for (;;)
798        if ((md->moptions & PCRE_NOTEOL) == 0)        if ((md->moptions & PCRE_NOTEOL) == 0)
799          {          {
800          if (clen == 0 ||          if (clen == 0 ||
801              (IS_NEWLINE(ptr) &&              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
802                 ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)                 ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)
803              ))              ))
804            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
# Line 784  for (;;) Line 835  for (;;)
835          if (ptr > start_subject)          if (ptr > start_subject)
836            {            {
837            const uschar *temp = ptr - 1;            const uschar *temp = ptr - 1;
838              if (temp < md->start_used_ptr) md->start_used_ptr = temp;
839  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
840            if (utf8) BACKCHAR(temp);            if (utf8) BACKCHAR(temp);
841  #endif  #endif
# Line 792  for (;;) Line 844  for (;;)
844            }            }
845          else left_word = 0;          else left_word = 0;
846    
847          if (clen > 0) right_word = c < 256 && (ctypes[c] & ctype_word) != 0;          if (clen > 0)
848            else right_word = 0;            right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
849            else              /* This is a fudge to ensure that if this is the */
850              {               /* last item in the pattern, we don't count it as */
851              reached_end--;  /* reached, thus disabling a partial match. */
852              right_word = 0;
853              }
854    
855          if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))          if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
856            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
# Line 812  for (;;) Line 869  for (;;)
869        if (clen > 0)        if (clen > 0)
870          {          {
871          BOOL OK;          BOOL OK;
872          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
873          switch(code[1])          switch(code[1])
874            {            {
875            case PT_ANY:            case PT_ANY:
# Line 820  for (;;) Line 877  for (;;)
877            break;            break;
878    
879            case PT_LAMP:            case PT_LAMP:
880            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
881            break;            break;
882    
883            case PT_GC:            case PT_GC:
884            OK = category == code[2];            OK = _pcre_ucp_gentype[prop->chartype] == code[2];
885            break;            break;
886    
887            case PT_PC:            case PT_PC:
888            OK = chartype == code[2];            OK = prop->chartype == code[2];
889            break;            break;
890    
891            case PT_SC:            case PT_SC:
892            OK = script == code[2];            OK = prop->script == code[2];
893            break;            break;
894    
895            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 852  for (;;) Line 909  for (;;)
909  /* ========================================================================== */  /* ========================================================================== */
910        /* These opcodes likewise inspect the subject character, but have an        /* These opcodes likewise inspect the subject character, but have an
911        argument that is not a data character. It is one of these opcodes:        argument that is not a data character. It is one of these opcodes:
912        OP_ANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE, OP_WORDCHAR,        OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,
913        OP_NOT_WORDCHAR. The value is loaded into d. */        OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */
914    
915        case OP_TYPEPLUS:        case OP_TYPEPLUS:
916        case OP_TYPEMINPLUS:        case OP_TYPEMINPLUS:
# Line 864  for (;;) Line 921  for (;;)
921          {          {
922          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
923              (c < 256 &&              (c < 256 &&
924                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                !IS_NEWLINE(ptr)  
               ) &&  
925                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
926            {            {
927            if (count > 0 && codevalue == OP_TYPEPOSPLUS)            if (count > 0 && codevalue == OP_TYPEPOSPLUS)
# Line 890  for (;;) Line 944  for (;;)
944          {          {
945          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
946              (c < 256 &&              (c < 256 &&
947                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                !IS_NEWLINE(ptr)  
               ) &&  
948                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
949            {            {
950            if (codevalue == OP_TYPEPOSQUERY)            if (codevalue == OP_TYPEPOSQUERY)
# Line 915  for (;;) Line 966  for (;;)
966          {          {
967          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
968              (c < 256 &&              (c < 256 &&
969                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                !IS_NEWLINE(ptr)  
               ) &&  
970                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
971            {            {
972            if (codevalue == OP_TYPEPOSSTAR)            if (codevalue == OP_TYPEPOSSTAR)
# Line 938  for (;;) Line 986  for (;;)
986          {          {
987          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
988              (c < 256 &&              (c < 256 &&
989                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                !IS_NEWLINE(ptr)  
               ) &&  
990                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
991            {            {
992            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
# Line 962  for (;;) Line 1007  for (;;)
1007          {          {
1008          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1009              (c < 256 &&              (c < 256 &&
1010                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                !IS_NEWLINE(ptr)  
               ) &&  
1011                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
1012            {            {
1013            if (codevalue == OP_TYPEPOSUPTO)            if (codevalue == OP_TYPEPOSUPTO)
# Line 996  for (;;) Line 1038  for (;;)
1038        if (clen > 0)        if (clen > 0)
1039          {          {
1040          BOOL OK;          BOOL OK;
1041          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
1042          switch(code[2])          switch(code[2])
1043            {            {
1044            case PT_ANY:            case PT_ANY:
# Line 1004  for (;;) Line 1046  for (;;)
1046            break;            break;
1047    
1048            case PT_LAMP:            case PT_LAMP:
1049            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
1050            break;            break;
1051    
1052            case PT_GC:            case PT_GC:
1053            OK = category == code[3];            OK = _pcre_ucp_gentype[prop->chartype] == code[3];
1054            break;            break;
1055    
1056            case PT_PC:            case PT_PC:
1057            OK = chartype == code[3];            OK = prop->chartype == code[3];
1058            break;            break;
1059    
1060            case PT_SC:            case PT_SC:
1061            OK = script == code[3];            OK = prop->script == code[3];
1062            break;            break;
1063    
1064            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 1045  for (;;) Line 1087  for (;;)
1087        case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:        case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
1088        count = current_state->count;  /* Already matched */        count = current_state->count;  /* Already matched */
1089        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1090        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1091          {          {
1092          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1093          int ncount = 0;          int ncount = 0;
# Line 1059  for (;;) Line 1101  for (;;)
1101            int nd;            int nd;
1102            int ndlen = 1;            int ndlen = 1;
1103            GETCHARLEN(nd, nptr, ndlen);            GETCHARLEN(nd, nptr, ndlen);
1104            if (_pcre_ucp_findprop(nd, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(nd) != ucp_M) break;
1105            ncount++;            ncount++;
1106            nptr += ndlen;            nptr += ndlen;
1107            }            }
# Line 1218  for (;;) Line 1260  for (;;)
1260        if (clen > 0)        if (clen > 0)
1261          {          {
1262          BOOL OK;          BOOL OK;
1263          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
1264          switch(code[2])          switch(code[2])
1265            {            {
1266            case PT_ANY:            case PT_ANY:
# Line 1226  for (;;) Line 1268  for (;;)
1268            break;            break;
1269    
1270            case PT_LAMP:            case PT_LAMP:
1271            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
1272            break;            break;
1273    
1274            case PT_GC:            case PT_GC:
1275            OK = category == code[3];            OK = _pcre_ucp_gentype[prop->chartype] == code[3];
1276            break;            break;
1277    
1278            case PT_PC:            case PT_PC:
1279            OK = chartype == code[3];            OK = prop->chartype == code[3];
1280            break;            break;
1281    
1282            case PT_SC:            case PT_SC:
1283            OK = script == code[3];            OK = prop->script == code[3];
1284            break;            break;
1285    
1286            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 1276  for (;;) Line 1318  for (;;)
1318        QS2:        QS2:
1319    
1320        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
1321        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1322          {          {
1323          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1324          int ncount = 0;          int ncount = 0;
# Line 1291  for (;;) Line 1333  for (;;)
1333            int nd;            int nd;
1334            int ndlen = 1;            int ndlen = 1;
1335            GETCHARLEN(nd, nptr, ndlen);            GETCHARLEN(nd, nptr, ndlen);
1336            if (_pcre_ucp_findprop(nd, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(nd) != ucp_M) break;
1337            ncount++;            ncount++;
1338            nptr += ndlen;            nptr += ndlen;
1339            }            }
# Line 1465  for (;;) Line 1507  for (;;)
1507        if (clen > 0)        if (clen > 0)
1508          {          {
1509          BOOL OK;          BOOL OK;
1510          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
1511          switch(code[4])          switch(code[4])
1512            {            {
1513            case PT_ANY:            case PT_ANY:
# Line 1473  for (;;) Line 1515  for (;;)
1515            break;            break;
1516    
1517            case PT_LAMP:            case PT_LAMP:
1518            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
1519            break;            break;
1520    
1521            case PT_GC:            case PT_GC:
1522            OK = category == code[5];            OK = _pcre_ucp_gentype[prop->chartype] == code[5];
1523            break;            break;
1524    
1525            case PT_PC:            case PT_PC:
1526            OK = chartype == code[5];            OK = prop->chartype == code[5];
1527            break;            break;
1528    
1529            case PT_SC:            case PT_SC:
1530            OK = script == code[5];            OK = prop->script == code[5];
1531            break;            break;
1532    
1533            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 1518  for (;;) Line 1560  for (;;)
1560        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
1561          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 4, 0); }
1562        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1563        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1564          {          {
1565          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1566          int ncount = 0;          int ncount = 0;
# Line 1532  for (;;) Line 1574  for (;;)
1574            int nd;            int nd;
1575            int ndlen = 1;            int ndlen = 1;
1576            GETCHARLEN(nd, nptr, ndlen);            GETCHARLEN(nd, nptr, ndlen);
1577            if (_pcre_ucp_findprop(nd, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(nd) != ucp_M) break;
1578            ncount++;            ncount++;
1579            nptr += ndlen;            nptr += ndlen;
1580            }            }
# Line 1712  for (;;) Line 1754  for (;;)
1754            other case of the character. */            other case of the character. */
1755    
1756  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
1757            othercase = _pcre_ucp_othercase(c);            othercase = UCD_OTHERCASE(c);
1758  #else  #else
1759            othercase = NOTACHAR;            othercase = NOTACHAR;
1760  #endif  #endif
# Line 1737  for (;;) Line 1779  for (;;)
1779        to wait for them to pass before continuing. */        to wait for them to pass before continuing. */
1780    
1781        case OP_EXTUNI:        case OP_EXTUNI:
1782        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1783          {          {
1784          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1785          int ncount = 0;          int ncount = 0;
# Line 1745  for (;;) Line 1787  for (;;)
1787            {            {
1788            int nclen = 1;            int nclen = 1;
1789            GETCHARLEN(c, nptr, nclen);            GETCHARLEN(c, nptr, nclen);
1790            if (_pcre_ucp_findprop(c, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(c) != ucp_M) break;
1791            ncount++;            ncount++;
1792            nptr += nclen;            nptr += nclen;
1793            }            }
# Line 1913  for (;;) Line 1955  for (;;)
1955            if (utf8 && d >= 128)            if (utf8 && d >= 128)
1956              {              {
1957  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
1958              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
1959  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
1960              }              }
1961            else            else
# Line 1951  for (;;) Line 1993  for (;;)
1993            if (utf8 && d >= 128)            if (utf8 && d >= 128)
1994              {              {
1995  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
1996              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
1997  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
1998              }              }
1999            else            else
# Line 1987  for (;;) Line 2029  for (;;)
2029            if (utf8 && d >= 128)            if (utf8 && d >= 128)
2030              {              {
2031  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2032              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
2033  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2034              }              }
2035            else            else
# Line 2019  for (;;) Line 2061  for (;;)
2061            if (utf8 && d >= 128)            if (utf8 && d >= 128)
2062              {              {
2063  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2064              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
2065  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2066              }              }
2067            else            else
# Line 2054  for (;;) Line 2096  for (;;)
2096            if (utf8 && d >= 128)            if (utf8 && d >= 128)
2097              {              {
2098  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2099              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
2100  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2101              }              }
2102            else            else
# Line 2162  for (;;) Line 2204  for (;;)
2204    
2205  /* ========================================================================== */  /* ========================================================================== */
2206        /* These are the opcodes for fancy brackets of various kinds. We have        /* These are the opcodes for fancy brackets of various kinds. We have
2207        to use recursion in order to handle them. */        to use recursion in order to handle them. The "always failing" assertion
2208          (?!) is optimised to OP_FAIL when compiling, so we have to support that,
2209          though the other "backtracking verbs" are not supported. */
2210    
2211          case OP_FAIL:
2212          forced_fail++;    /* Count FAILs for multiple states */
2213          break;
2214    
2215        case OP_ASSERT:        case OP_ASSERT:
2216        case OP_ASSERT_NOT:        case OP_ASSERT_NOT:
# Line 2200  for (;;) Line 2248  for (;;)
2248          {          {
2249          int local_offsets[1000];          int local_offsets[1000];
2250          int local_workspace[1000];          int local_workspace[1000];
2251          int condcode = code[LINK_SIZE+1];          int codelink = GET(code, 1);
2252            int condcode;
2253    
2254            /* Because of the way auto-callout works during compile, a callout item
2255            is inserted between OP_COND and an assertion condition. This does not
2256            happen for the other conditions. */
2257    
2258            if (code[LINK_SIZE+1] == OP_CALLOUT)
2259              {
2260              rrc = 0;
2261              if (pcre_callout != NULL)
2262                {
2263                pcre_callout_block cb;
2264                cb.version          = 1;   /* Version 1 of the callout block */
2265                cb.callout_number   = code[LINK_SIZE+2];
2266                cb.offset_vector    = offsets;
2267                cb.subject          = (PCRE_SPTR)start_subject;
2268                cb.subject_length   = end_subject - start_subject;
2269                cb.start_match      = current_subject - start_subject;
2270                cb.current_position = ptr - start_subject;
2271                cb.pattern_position = GET(code, LINK_SIZE + 3);
2272                cb.next_item_length = GET(code, 3 + 2*LINK_SIZE);
2273                cb.capture_top      = 1;
2274                cb.capture_last     = -1;
2275                cb.callout_data     = md->callout_data;
2276                if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
2277                }
2278              if (rrc > 0) break;                      /* Fail this thread */
2279              code += _pcre_OP_lengths[OP_CALLOUT];    /* Skip callout data */
2280              }
2281    
2282            condcode = code[LINK_SIZE+1];
2283    
2284          /* Back reference conditions are not supported */          /* Back reference conditions are not supported */
2285    
# Line 2209  for (;;) Line 2288  for (;;)
2288          /* The DEFINE condition is always false */          /* The DEFINE condition is always false */
2289    
2290          if (condcode == OP_DEF)          if (condcode == OP_DEF)
2291            {            { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
           ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0);  
           }  
2292    
2293          /* The only supported version of OP_RREF is for the value RREF_ANY,          /* The only supported version of OP_RREF is for the value RREF_ANY,
2294          which means "test if in any recursion". We can't test for specifically          which means "test if in any recursion". We can't test for specifically
# Line 2221  for (;;) Line 2298  for (;;)
2298            {            {
2299            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE+2);
2300            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
2301            if (recursing > 0) { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }            if (recursing > 0)
2302              else { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); }              { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }
2303              else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2304            }            }
2305    
2306          /* Otherwise, the condition is an assertion */          /* Otherwise, the condition is an assertion */
# Line 2252  for (;;) Line 2330  for (;;)
2330                  (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))                  (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
2331              { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); }              { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); }
2332            else            else
2333              { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); }              { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2334            }            }
2335          }          }
2336        break;        break;
# Line 2404  for (;;) Line 2482  for (;;)
2482        /* Handle callouts */        /* Handle callouts */
2483    
2484        case OP_CALLOUT:        case OP_CALLOUT:
2485          rrc = 0;
2486        if (pcre_callout != NULL)        if (pcre_callout != NULL)
2487          {          {
         int rrc;  
2488          pcre_callout_block cb;          pcre_callout_block cb;
2489          cb.version          = 1;   /* Version 1 of the callout block */          cb.version          = 1;   /* Version 1 of the callout block */
2490          cb.callout_number   = code[1];          cb.callout_number   = code[1];
# Line 2421  for (;;) Line 2499  for (;;)
2499          cb.capture_last     = -1;          cb.capture_last     = -1;
2500          cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
2501          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
         if (rrc == 0) { ADD_ACTIVE(state_offset + 2 + 2*LINK_SIZE, 0); }  
2502          }          }
2503          if (rrc == 0)
2504            { ADD_ACTIVE(state_offset + _pcre_OP_lengths[OP_CALLOUT], 0); }
2505        break;        break;
2506    
2507    
# Line 2438  for (;;) Line 2517  for (;;)
2517    /* We have finished the processing at the current subject character. If no    /* We have finished the processing at the current subject character. If no
2518    new states have been set for the next character, we have found all the    new states have been set for the next character, we have found all the
2519    matches that we are going to find. If we are at the top level and partial    matches that we are going to find. If we are at the top level and partial
2520    matching has been requested, check for appropriate conditions. */    matching has been requested, check for appropriate conditions. The "forced_
2521      fail" variable counts the number of (*F) encountered for the character. If it
2522      is equal to the original active_count (saved in workspace[1]) it means that
2523      (*F) was found on every active state. In this case we don't want to give a
2524      partial match. */
2525    
2526    if (new_count <= 0)    if (new_count <= 0)
2527      {      {
2528      if (match_count < 0 &&                     /* No matches found */      if (rlevel == 1 &&                               /* Top level, and */
2529          rlevel == 1 &&                         /* Top level match function */          reached_end != workspace[1] &&               /* Not all reached end */
2530          (md->moptions & PCRE_PARTIAL) != 0 &&  /* Want partial matching */          forced_fail != workspace[1] &&               /* Not all forced fail & */
2531          ptr >= end_subject &&                  /* Reached end of subject */          (                                            /* either... */
2532          ptr > current_subject)                 /* Matched non-empty string */          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
2533            ||                                           /* or... */
2534            ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
2535             match_count < 0)                            /* no matches */
2536            ) &&                                         /* And... */
2537            ptr >= end_subject &&                     /* Reached end of subject */
2538            ptr > current_subject)                    /* Matched non-empty string */
2539        {        {
2540        if (offsetcount >= 2)        if (offsetcount >= 2)
2541          {          {
2542          offsets[0] = current_subject - start_subject;          offsets[0] = md->start_used_ptr - start_subject;
2543          offsets[1] = end_subject - start_subject;          offsets[1] = end_subject - start_subject;
2544          }          }
2545        match_count = PCRE_ERROR_PARTIAL;        match_count = PCRE_ERROR_PARTIAL;
# Line 2505  Returns:          > 0 => number of match Line 2594  Returns:          > 0 => number of match
2594                   < -1 => some kind of unexpected problem                   < -1 => some kind of unexpected problem
2595  */  */
2596    
2597  PCRE_EXP_DEFN int  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
2598  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
2599    const char *subject, int length, int start_offset, int options, int *offsets,    const char *subject, int length, int start_offset, int options, int *offsets,
2600    int offsetcount, int *workspace, int wscount)    int offsetcount, int *workspace, int wscount)
# Line 2604  if ((md->moptions & (PCRE_BSR_ANYCRLF|PC Line 2693  if ((md->moptions & (PCRE_BSR_ANYCRLF|PC
2693      md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);      md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
2694  #ifdef BSR_ANYCRLF  #ifdef BSR_ANYCRLF
2695    else md->moptions |= PCRE_BSR_ANYCRLF;    else md->moptions |= PCRE_BSR_ANYCRLF;
2696  #endif  #endif
2697    }    }
2698    
2699  /* Handle different types of newline. The three bits give eight cases. If  /* Handle different types of newline. The three bits give eight cases. If
2700  nothing is set at run time, whatever was used at compile time applies. */  nothing is set at run time, whatever was used at compile time applies. */
# Line 2614  switch ((((options & PCRE_NEWLINE_BITS) Line 2703  switch ((((options & PCRE_NEWLINE_BITS)
2703           PCRE_NEWLINE_BITS)           PCRE_NEWLINE_BITS)
2704    {    {
2705    case 0: newline = NEWLINE; break;   /* Compile-time default */    case 0: newline = NEWLINE; break;   /* Compile-time default */
2706    case PCRE_NEWLINE_CR: newline = '\r'; break;    case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
2707    case PCRE_NEWLINE_LF: newline = '\n'; break;    case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
2708    case PCRE_NEWLINE_CR+    case PCRE_NEWLINE_CR+
2709         PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;         PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
2710    case PCRE_NEWLINE_ANY: newline = -1; break;    case PCRE_NEWLINE_ANY: newline = -1; break;
2711    case PCRE_NEWLINE_ANYCRLF: newline = -2; break;    case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
2712    default: return PCRE_ERROR_BADNEWLINE;    default: return PCRE_ERROR_BADNEWLINE;
# Line 2713  if ((re->flags & PCRE_REQCHSET) != 0) Line 2802  if ((re->flags & PCRE_REQCHSET) != 0)
2802    }    }
2803    
2804  /* 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
2805  failed match. Unless restarting, optimize by moving to the first match  failed match. If not restarting, perform certain optimizations at the start of
2806  character if possible, when not anchored. Then unless wanting a partial match,  a match. */
 check for a required later character. */  
2807    
2808  for (;;)  for (;;)
2809    {    {
# Line 2725  for (;;) Line 2813  for (;;)
2813      {      {
2814      const uschar *save_end_subject = end_subject;      const uschar *save_end_subject = end_subject;
2815    
2816      /* Advance to a unique first char if possible. If firstline is TRUE, the      /* If firstline is TRUE, the start of the match is constrained to the first
2817      start of the match is constrained to the first line of a multiline string.      line of a multiline string. Implement this by temporarily adjusting
2818      Implement this by temporarily adjusting end_subject so that we stop      end_subject so that we stop scanning at a newline. If the match fails at
2819      scanning at a newline. If the match fails at the newline, later code breaks      the newline, later code breaks this loop. */
     this loop. */  
2820    
2821      if (firstline)      if (firstline)
2822        {        {
2823        const uschar *t = current_subject;        USPTR t = current_subject;
2824    #ifdef SUPPORT_UTF8
2825          if (utf8)
2826            {
2827            while (t < md->end_subject && !IS_NEWLINE(t))
2828              {
2829              t++;
2830              while (t < end_subject && (*t & 0xc0) == 0x80) t++;
2831              }
2832            }
2833          else
2834    #endif
2835        while (t < md->end_subject && !IS_NEWLINE(t)) t++;        while (t < md->end_subject && !IS_NEWLINE(t)) t++;
2836        end_subject = t;        end_subject = t;
2837        }        }
2838    
2839      if (first_byte >= 0)      /* There are some optimizations that avoid running the match if a known
2840        starting point is not found, or if a known later character is not present.
2841        However, there is an option that disables these, for testing and for
2842        ensuring that all callouts do actually occur. */
2843    
2844        if ((options & PCRE_NO_START_OPTIMIZE) == 0)
2845        {        {
       if (first_byte_caseless)  
         while (current_subject < end_subject &&  
                lcc[*current_subject] != first_byte)  
           current_subject++;  
       else  
         while (current_subject < end_subject && *current_subject != first_byte)  
           current_subject++;  
       }  
2846    
2847      /* Or to just after a linebreak for a multiline match if possible */        /* Advance to a known first byte. */
2848    
2849      else if (startline)        if (first_byte >= 0)
       {  
       if (current_subject > md->start_subject + start_offset)  
2850          {          {
2851          while (current_subject <= end_subject && !WAS_NEWLINE(current_subject))          if (first_byte_caseless)
2852            current_subject++;            while (current_subject < end_subject &&
2853                     lcc[*current_subject] != first_byte)
2854                current_subject++;
2855            else
2856              while (current_subject < end_subject &&
2857                     *current_subject != first_byte)
2858                current_subject++;
2859            }
2860    
2861          /* If we have just passed a CR and the newline option is ANY or        /* Or to just after a linebreak for a multiline match if possible */
2862          ANYCRLF, and we are now at a LF, advance the match position by one more  
2863          character. */        else if (startline)
2864            {
2865          if (current_subject[-1] == '\r' &&          if (current_subject > md->start_subject + start_offset)
2866               (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&            {
2867               current_subject < end_subject &&  #ifdef SUPPORT_UTF8
2868               *current_subject == '\n')            if (utf8)
2869            current_subject++;              {
2870                while (current_subject < end_subject &&
2871                       !WAS_NEWLINE(current_subject))
2872                  {
2873                  current_subject++;
2874                  while(current_subject < end_subject &&
2875                        (*current_subject & 0xc0) == 0x80)
2876                    current_subject++;
2877                  }
2878                }
2879              else
2880    #endif
2881              while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
2882                current_subject++;
2883    
2884              /* If we have just passed a CR and the newline option is ANY or
2885              ANYCRLF, and we are now at a LF, advance the match position by one
2886              more character. */
2887    
2888              if (current_subject[-1] == CHAR_CR &&
2889                   (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
2890                   current_subject < end_subject &&
2891                   *current_subject == CHAR_NL)
2892                current_subject++;
2893              }
2894          }          }
       }  
2895    
2896      /* Or to a non-unique first char after study */        /* Or to a non-unique first char after study */
2897    
2898      else if (start_bits != NULL)        else if (start_bits != NULL)
       {  
       while (current_subject < end_subject)  
2899          {          {
2900          register unsigned int c = *current_subject;          while (current_subject < end_subject)
2901          if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++;            {
2902            else break;            register unsigned int c = *current_subject;
2903              if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++;
2904                else break;
2905              }
2906          }          }
2907        }        }
2908    
# Line 2800  for (;;) Line 2924  for (;;)
2924    showed up when somebody was matching /^C/ on a 32-megabyte string... so we    showed up when somebody was matching /^C/ on a 32-megabyte string... so we
2925    don't do this when the string is sufficiently long.    don't do this when the string is sufficiently long.
2926    
2927    ALSO: this processing is disabled when partial matching is requested.    ALSO: this processing is disabled when partial matching is requested, and can
2928    */    also be explicitly deactivated. Furthermore, we have to disable when
2929      restarting after a partial match, because the required character may have
2930      already been matched. */
2931    
2932    if (req_byte >= 0 &&    if ((options & PCRE_NO_START_OPTIMIZE) == 0 &&
2933          req_byte >= 0 &&
2934        end_subject - current_subject < REQ_BYTE_MAX &&        end_subject - current_subject < REQ_BYTE_MAX &&
2935        (options & PCRE_PARTIAL) == 0)        (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_RESTART)) == 0)
2936      {      {
2937      register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);      register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);
2938    
# Line 2845  for (;;) Line 2972  for (;;)
2972    
2973    /* OK, now we can do the business */    /* OK, now we can do the business */
2974    
2975      md->start_used_ptr = current_subject;
2976    
2977    rc = internal_dfa_exec(    rc = internal_dfa_exec(
2978      md,                                /* fixed match data */      md,                                /* fixed match data */
2979      md->start_code,                    /* this subexpression's code */      md->start_code,                    /* this subexpression's code */
# Line 2879  for (;;) Line 3008  for (;;)
3008    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
3009    or ANY or ANYCRLF, advance the match position by one more character. */    or ANY or ANYCRLF, advance the match position by one more character. */
3010    
3011    if (current_subject[-1] == '\r' &&    if (current_subject[-1] == CHAR_CR &&
3012        current_subject < end_subject &&        current_subject < end_subject &&
3013        *current_subject == '\n' &&        *current_subject == CHAR_NL &&
3014        (re->flags & PCRE_HASCRORLF) == 0 &&        (re->flags & PCRE_HASCRORLF) == 0 &&
3015          (md->nltype == NLTYPE_ANY ||          (md->nltype == NLTYPE_ANY ||
3016           md->nltype == NLTYPE_ANYCRLF ||           md->nltype == NLTYPE_ANYCRLF ||

Legend:
Removed from v.231  
changed lines
  Added in v.439

  ViewVC Help
Powered by ViewVC 1.1.5