/[pcre]/code/branches/pcre16/pcre_dfa_exec.c
ViewVC logotype

Diff of /code/branches/pcre16/pcre_dfa_exec.c

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

revision 211 by ph10, Thu Aug 9 09:52:43 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 1080  for (;;) Line 1122  for (;;)
1122          int ncount = 0;          int ncount = 0;
1123          switch (c)          switch (c)
1124            {            {
           case 0x000d:  
           if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;  
           /* Fall through */  
           case 0x000a:  
1125            case 0x000b:            case 0x000b:
1126            case 0x000c:            case 0x000c:
1127            case 0x0085:            case 0x0085:
1128            case 0x2028:            case 0x2028:
1129            case 0x2029:            case 0x2029:
1130              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1131              goto ANYNL01;
1132    
1133              case 0x000d:
1134              if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1135              /* Fall through */
1136    
1137              ANYNL01:
1138              case 0x000a:
1139            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
1140              {              {
1141              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
# Line 1097  for (;;) Line 1144  for (;;)
1144            count++;            count++;
1145            ADD_NEW_DATA(-state_offset, count, ncount);            ADD_NEW_DATA(-state_offset, count, ncount);
1146            break;            break;
1147    
1148            default:            default:
1149            break;            break;
1150            }            }
# Line 1212  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 1220  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 1270  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 1285  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 1313  for (;;) Line 1361  for (;;)
1361          int ncount = 0;          int ncount = 0;
1362          switch (c)          switch (c)
1363            {            {
           case 0x000d:  
           if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;  
           /* Fall through */  
           case 0x000a:  
1364            case 0x000b:            case 0x000b:
1365            case 0x000c:            case 0x000c:
1366            case 0x0085:            case 0x0085:
1367            case 0x2028:            case 0x2028:
1368            case 0x2029:            case 0x2029:
1369              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1370              goto ANYNL02;
1371    
1372              case 0x000d:
1373              if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1374              /* Fall through */
1375    
1376              ANYNL02:
1377              case 0x000a:
1378            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
1379                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
1380              {              {
# Line 1330  for (;;) Line 1383  for (;;)
1383              }              }
1384            ADD_NEW_DATA(-(state_offset + count), 0, ncount);            ADD_NEW_DATA(-(state_offset + count), 0, ncount);
1385            break;            break;
1386    
1387            default:            default:
1388            break;            break;
1389            }            }
# Line 1453  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 1461  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 1506  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 1520  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 1545  for (;;) Line 1599  for (;;)
1599          int ncount = 0;          int ncount = 0;
1600          switch (c)          switch (c)
1601            {            {
           case 0x000d:  
           if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;  
           /* Fall through */  
           case 0x000a:  
1602            case 0x000b:            case 0x000b:
1603            case 0x000c:            case 0x000c:
1604            case 0x0085:            case 0x0085:
1605            case 0x2028:            case 0x2028:
1606            case 0x2029:            case 0x2029:
1607              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1608              goto ANYNL03;
1609    
1610              case 0x000d:
1611              if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1612              /* Fall through */
1613    
1614              ANYNL03:
1615              case 0x000a:
1616            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
1617              {              {
1618              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
# Line 1564  for (;;) Line 1623  for (;;)
1623            else            else
1624              { ADD_NEW_DATA(-state_offset, count, ncount); }              { ADD_NEW_DATA(-state_offset, count, ncount); }
1625            break;            break;
1626    
1627            default:            default:
1628            break;            break;
1629            }            }
# Line 1694  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 1719  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 1727  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 1744  for (;;) Line 1804  for (;;)
1804        case OP_ANYNL:        case OP_ANYNL:
1805        if (clen > 0) switch(c)        if (clen > 0) switch(c)
1806          {          {
         case 0x000a:  
1807          case 0x000b:          case 0x000b:
1808          case 0x000c:          case 0x000c:
1809          case 0x0085:          case 0x0085:
1810          case 0x2028:          case 0x2028:
1811          case 0x2029:          case 0x2029:
1812            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1813    
1814            case 0x000a:
1815          ADD_NEW(state_offset + 1, 0);          ADD_NEW(state_offset + 1, 0);
1816          break;          break;
1817    
1818          case 0x000d:          case 0x000d:
1819          if (ptr + 1 < end_subject && ptr[1] == 0x0a)          if (ptr + 1 < end_subject && ptr[1] == 0x0a)
1820            {            {
# Line 1892  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 1930  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 1966  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 1998  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 2033  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 2141  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 2179  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 2188  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 2200  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 2231  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 2383  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 2400  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 2417  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 2484  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 2574  md->end_subject = end_subject; Line 2684  md->end_subject = end_subject;
2684  md->moptions = options;  md->moptions = options;
2685  md->poptions = re->options;  md->poptions = re->options;
2686    
2687    /* If the BSR option is not set at match time, copy what was set
2688    at compile time. */
2689    
2690    if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
2691      {
2692      if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
2693        md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
2694    #ifdef BSR_ANYCRLF
2695      else md->moptions |= PCRE_BSR_ANYCRLF;
2696    #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. */
2701    
# Line 2581  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 2644  if (md->tables == NULL) md->tables = _pc Line 2766  if (md->tables == NULL) md->tables = _pc
2766  used in a loop when finding where to start. */  used in a loop when finding where to start. */
2767    
2768  lcc = md->tables + lcc_offset;  lcc = md->tables + lcc_offset;
2769  startline = (re->options & PCRE_STARTLINE) != 0;  startline = (re->flags & PCRE_STARTLINE) != 0;
2770  firstline = (re->options & PCRE_FIRSTLINE) != 0;  firstline = (re->options & PCRE_FIRSTLINE) != 0;
2771    
2772  /* Set up the first character to match, if available. The first_byte value is  /* Set up the first character to match, if available. The first_byte value is
# Line 2655  studied, there may be a bitmap of possib Line 2777  studied, there may be a bitmap of possib
2777    
2778  if (!anchored)  if (!anchored)
2779    {    {
2780    if ((re->options & PCRE_FIRSTSET) != 0)    if ((re->flags & PCRE_FIRSTSET) != 0)
2781      {      {
2782      first_byte = re->first_byte & 255;      first_byte = re->first_byte & 255;
2783      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)
# Line 2672  if (!anchored) Line 2794  if (!anchored)
2794  /* For anchored or unanchored matches, there may be a "last known required  /* For anchored or unanchored matches, there may be a "last known required
2795  character" set. */  character" set. */
2796    
2797  if ((re->options & PCRE_REQCHSET) != 0)  if ((re->flags & PCRE_REQCHSET) != 0)
2798    {    {
2799    req_byte = re->req_byte & 255;    req_byte = re->req_byte & 255;
2800    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;
# Line 2680  if ((re->options & PCRE_REQCHSET) != 0) Line 2802  if ((re->options & 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 2692  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          /* Or to just after a linebreak for a multiline match if possible */
2862    
2863          /* If we have just passed a CR and the newline option is ANY or        else if (startline)
2864          ANYCRLF, and we are now at a LF, advance the match position by one more          {
2865          character. */          if (current_subject > md->start_subject + start_offset)
2866              {
2867          if (current_subject[-1] == '\r' &&  #ifdef SUPPORT_UTF8
2868               (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&            if (utf8)
2869               current_subject < end_subject &&              {
2870               *current_subject == '\n')              while (current_subject < end_subject &&
2871            current_subject++;                     !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 2767  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 2812  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 2842  for (;;) Line 3004  for (;;)
3004      }      }
3005    if (current_subject > end_subject) break;    if (current_subject > end_subject) break;
3006    
3007    /* If we have just passed a CR and the newline option is CRLF or ANY or    /* If we have just passed a CR and we are now at a LF, and the pattern does
3008    ANYCRLF, and we are now at a LF, advance the match position by one more    not contain any explicit matches for \r or \n, and the newline option is CRLF
3009    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         (md->nltype == NLTYPE_ANY ||        current_subject < end_subject &&
3013          md->nltype == NLTYPE_ANYCRLF ||        *current_subject == CHAR_NL &&
3014          md->nllen == 2) &&        (re->flags & PCRE_HASCRORLF) == 0 &&
3015         current_subject < end_subject &&          (md->nltype == NLTYPE_ANY ||
3016         *current_subject == '\n')           md->nltype == NLTYPE_ANYCRLF ||
3017             md->nllen == 2))
3018      current_subject++;      current_subject++;
3019    
3020    }   /* "Bumpalong" loop */    }   /* "Bumpalong" loop */

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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12