/[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 130 by ph10, Mon Mar 26 15:09:47 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
77    #include "config.h"
78    #endif
79    
80  #define NLBLOCK md             /* Block containing newline information */  #define NLBLOCK md             /* Block containing newline information */
81  #define PSSTART start_subject  /* Field containing processed string start */  #define PSSTART start_subject  /* Field containing processed string start */
82  #define PSEND   end_subject    /* Field containing processed string end */  #define PSEND   end_subject    /* Field containing processed string end */
# Line 56  applications. */ Line 89  applications. */
89  #define SP "                   "  #define SP "                   "
90    
91    
   
92  /*************************************************  /*************************************************
93  *      Code parameters and static tables         *  *      Code parameters and static tables         *
94  *************************************************/  *************************************************/
95    
96  /* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes  /* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes
97  into others, under special conditions. A gap of 20 between the blocks should be  into others, under special conditions. A gap of 20 between the blocks should be
98  enough. */  enough. The resulting opcodes don't have to be less than 256 because they are
99    never stored, so we push them well clear of the normal opcodes. */
100    
101  #define OP_PROP_EXTRA 100  #define OP_PROP_EXTRA       300
102  #define OP_EXTUNI_EXTRA 120  #define OP_EXTUNI_EXTRA     320
103  #define OP_ANYNL_EXTRA 140  #define OP_ANYNL_EXTRA      340
104    #define OP_HSPACE_EXTRA     360
105    #define OP_VSPACE_EXTRA     380
106    
107    
108  /* This table identifies those opcodes that are followed immediately by a  /* This table identifies those opcodes that are followed immediately by a
109  character that is to be tested in some way. This makes is possible to  character that is to be tested in some way. This makes is possible to
110  centralize the loading of these characters. In the case of Type * etc, the  centralize the loading of these characters. In the case of Type * etc, the
111  "character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a  "character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a
112  small value. */  small value. ***NOTE*** If the start of this table is modified, the two tables
113    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, 0, 0, 0, 0, 0,  /* \A, \G, \B, \b, \D, \d, \S, \s, \W, \w */    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
118    0, 0,                          /* Any, Anybyte                           */    0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */
119    0, 0, 0, 0,                    /* NOTPROP, PROP, EXTUNI, ANYNL           */    0, 0, 0,                       /* Any, AllAny, Anybyte                   */
120      0, 0, 0,                       /* NOTPROP, PROP, EXTUNI                  */
121      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, ^, $                      */
123    1,                             /* Char                                   */    1,                             /* Char                                   */
124    1,                             /* Charnc                                 */    1,                             /* Charnc                                 */
# Line 120  static uschar coptable[] = { Line 158  static uschar coptable[] = {
158    0,                             /* CREF                                   */    0,                             /* CREF                                   */
159    0,                             /* RREF                                   */    0,                             /* RREF                                   */
160    0,                             /* DEF                                    */    0,                             /* DEF                                    */
161    0, 0                           /* BRAZERO, BRAMINZERO                    */    0, 0,                          /* BRAZERO, BRAMINZERO                    */
162      0, 0, 0, 0,                    /* PRUNE, SKIP, THEN, COMMIT              */
163      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,
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,
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 211  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 377  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 442  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 499  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;
     int chartype, script;  
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 532  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 555  for (;;) Line 603  for (;;)
603      permitted.      permitted.
604    
605      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
606      argument that is not a data character - but is always one byte long.      argument that is not a data character - but is always one byte long. We
607      Unfortunately, we have to take special action to deal with  \P, \p, and      have to take special action to deal with  \P, \p, \H, \h, \V, \v and \X in
608      \X in this case. To keep the other cases fast, convert these ones to new      this case. To keep the other cases fast, convert these ones to new opcodes.
609      opcodes. */      */
610    
611      if (coptable[codevalue] > 0)      if (coptable[codevalue] > 0)
612        {        {
# Line 576  for (;;) Line 624  for (;;)
624            case OP_PROP: codevalue += OP_PROP_EXTRA; break;            case OP_PROP: codevalue += OP_PROP_EXTRA; break;
625            case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;            case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
626            case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;            case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;
627              case OP_NOT_HSPACE:
628              case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;
629              case OP_NOT_VSPACE:
630              case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;
631            default: break;            default: break;
632            }            }
633          }          }
# Line 609  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 676  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 714  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 729  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 766  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 774  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 783  for (;;) Line 858  for (;;)
858        break;        break;
859    
860    
 #ifdef SUPPORT_UCP  
   
861        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
862        /* Check the next character by Unicode property. We will get here only        /* Check the next character by Unicode property. We will get here only
863        if the support is in the binary; otherwise a compile-time error occurs.        if the support is in the binary; otherwise a compile-time error occurs.
864        */        */
865    
866    #ifdef SUPPORT_UCP
867        case OP_PROP:        case OP_PROP:
868        case OP_NOTPROP:        case OP_NOTPROP:
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 803  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 835  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 847  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 873  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 898  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 921  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 945  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 970  for (;;) Line 1029  for (;;)
1029        argument. It keeps the code above fast for the other cases. The argument        argument. It keeps the code above fast for the other cases. The argument
1030        is in the d variable. */        is in the d variable. */
1031    
1032    #ifdef SUPPORT_UCP
1033        case OP_PROP_EXTRA + OP_TYPEPLUS:        case OP_PROP_EXTRA + OP_TYPEPLUS:
1034        case OP_PROP_EXTRA + OP_TYPEMINPLUS:        case OP_PROP_EXTRA + OP_TYPEMINPLUS:
1035        case OP_PROP_EXTRA + OP_TYPEPOSPLUS:        case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
# Line 978  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 986  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 1027  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 1041  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 1049  for (;;) Line 1109  for (;;)
1109          ADD_NEW_DATA(-state_offset, count, ncount);          ADD_NEW_DATA(-state_offset, count, ncount);
1110          }          }
1111        break;        break;
1112    #endif
1113    
1114        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1115        case OP_ANYNL_EXTRA + OP_TYPEPLUS:        case OP_ANYNL_EXTRA + OP_TYPEPLUS:
# Line 1061  for (;;) Line 1122  for (;;)
1122          int ncount = 0;          int ncount = 0;
1123          switch (c)          switch (c)
1124            {            {
1125              case 0x000b:
1126              case 0x000c:
1127              case 0x0085:
1128              case 0x2028:
1129              case 0x2029:
1130              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1131              goto ANYNL01;
1132    
1133            case 0x000d:            case 0x000d:
1134            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1135            /* Fall through */            /* Fall through */
1136    
1137              ANYNL01:
1138              case 0x000a:
1139              if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
1140                {
1141                active_count--;           /* Remove non-match possibility */
1142                next_active_state--;
1143                }
1144              count++;
1145              ADD_NEW_DATA(-state_offset, count, ncount);
1146              break;
1147    
1148              default:
1149              break;
1150              }
1151            }
1152          break;
1153    
1154          /*-----------------------------------------------------------------*/
1155          case OP_VSPACE_EXTRA + OP_TYPEPLUS:
1156          case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:
1157          case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:
1158          count = current_state->count;  /* Already matched */
1159          if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1160          if (clen > 0)
1161            {
1162            BOOL OK;
1163            switch (c)
1164              {
1165            case 0x000a:            case 0x000a:
1166            case 0x000b:            case 0x000b:
1167            case 0x000c:            case 0x000c:
1168              case 0x000d:
1169            case 0x0085:            case 0x0085:
1170            case 0x2028:            case 0x2028:
1171            case 0x2029:            case 0x2029:
1172            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)            OK = TRUE;
1173              break;
1174    
1175              default:
1176              OK = FALSE;
1177              break;
1178              }
1179    
1180            if (OK == (d == OP_VSPACE))
1181              {
1182              if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)
1183              {              {
1184              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
1185              next_active_state--;              next_active_state--;
1186              }              }
1187            count++;            count++;
1188            ADD_NEW_DATA(-state_offset, count, ncount);            ADD_NEW_DATA(-state_offset, count, 0);
1189              }
1190            }
1191          break;
1192    
1193          /*-----------------------------------------------------------------*/
1194          case OP_HSPACE_EXTRA + OP_TYPEPLUS:
1195          case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:
1196          case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:
1197          count = current_state->count;  /* Already matched */
1198          if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1199          if (clen > 0)
1200            {
1201            BOOL OK;
1202            switch (c)
1203              {
1204              case 0x09:      /* HT */
1205              case 0x20:      /* SPACE */
1206              case 0xa0:      /* NBSP */
1207              case 0x1680:    /* OGHAM SPACE MARK */
1208              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1209              case 0x2000:    /* EN QUAD */
1210              case 0x2001:    /* EM QUAD */
1211              case 0x2002:    /* EN SPACE */
1212              case 0x2003:    /* EM SPACE */
1213              case 0x2004:    /* THREE-PER-EM SPACE */
1214              case 0x2005:    /* FOUR-PER-EM SPACE */
1215              case 0x2006:    /* SIX-PER-EM SPACE */
1216              case 0x2007:    /* FIGURE SPACE */
1217              case 0x2008:    /* PUNCTUATION SPACE */
1218              case 0x2009:    /* THIN SPACE */
1219              case 0x200A:    /* HAIR SPACE */
1220              case 0x202f:    /* NARROW NO-BREAK SPACE */
1221              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1222              case 0x3000:    /* IDEOGRAPHIC SPACE */
1223              OK = TRUE;
1224            break;            break;
1225    
1226            default:            default:
1227              OK = FALSE;
1228            break;            break;
1229            }            }
1230    
1231            if (OK == (d == OP_HSPACE))
1232              {
1233              if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)
1234                {
1235                active_count--;           /* Remove non-match possibility */
1236                next_active_state--;
1237                }
1238              count++;
1239              ADD_NEW_DATA(-state_offset, count, 0);
1240              }
1241          }          }
1242        break;        break;
1243    
1244        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1245    #ifdef SUPPORT_UCP
1246        case OP_PROP_EXTRA + OP_TYPEQUERY:        case OP_PROP_EXTRA + OP_TYPEQUERY:
1247        case OP_PROP_EXTRA + OP_TYPEMINQUERY:        case OP_PROP_EXTRA + OP_TYPEMINQUERY:
1248        case OP_PROP_EXTRA + OP_TYPEPOSQUERY:        case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
# Line 1102  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 1110  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 1160  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 1175  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            }            }
1340          ADD_NEW_DATA(-(state_offset + count), 0, ncount);          ADD_NEW_DATA(-(state_offset + count), 0, ncount);
1341          }          }
1342        break;        break;
1343    #endif
1344    
1345        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1346        case OP_ANYNL_EXTRA + OP_TYPEQUERY:        case OP_ANYNL_EXTRA + OP_TYPEQUERY:
# Line 1202  for (;;) Line 1361  for (;;)
1361          int ncount = 0;          int ncount = 0;
1362          switch (c)          switch (c)
1363            {            {
1364              case 0x000b:
1365              case 0x000c:
1366              case 0x0085:
1367              case 0x2028:
1368              case 0x2029:
1369              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1370              goto ANYNL02;
1371    
1372            case 0x000d:            case 0x000d:
1373            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1374            /* Fall through */            /* Fall through */
1375    
1376              ANYNL02:
1377              case 0x000a:
1378              if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
1379                  codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
1380                {
1381                active_count--;           /* Remove non-match possibility */
1382                next_active_state--;
1383                }
1384              ADD_NEW_DATA(-(state_offset + count), 0, ncount);
1385              break;
1386    
1387              default:
1388              break;
1389              }
1390            }
1391          break;
1392    
1393          /*-----------------------------------------------------------------*/
1394          case OP_VSPACE_EXTRA + OP_TYPEQUERY:
1395          case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:
1396          case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:
1397          count = 2;
1398          goto QS4;
1399    
1400          case OP_VSPACE_EXTRA + OP_TYPESTAR:
1401          case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:
1402          case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:
1403          count = 0;
1404    
1405          QS4:
1406          ADD_ACTIVE(state_offset + 2, 0);
1407          if (clen > 0)
1408            {
1409            BOOL OK;
1410            switch (c)
1411              {
1412            case 0x000a:            case 0x000a:
1413            case 0x000b:            case 0x000b:
1414            case 0x000c:            case 0x000c:
1415              case 0x000d:
1416            case 0x0085:            case 0x0085:
1417            case 0x2028:            case 0x2028:
1418            case 0x2029:            case 0x2029:
1419            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||            OK = TRUE;
1420                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)            break;
1421    
1422              default:
1423              OK = FALSE;
1424              break;
1425              }
1426            if (OK == (d == OP_VSPACE))
1427              {
1428              if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||
1429                  codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)
1430              {              {
1431              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
1432              next_active_state--;              next_active_state--;
1433              }              }
1434            ADD_NEW_DATA(-(state_offset + count), 0, ncount);            ADD_NEW_DATA(-(state_offset + count), 0, 0);
1435              }
1436            }
1437          break;
1438    
1439          /*-----------------------------------------------------------------*/
1440          case OP_HSPACE_EXTRA + OP_TYPEQUERY:
1441          case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:
1442          case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:
1443          count = 2;
1444          goto QS5;
1445    
1446          case OP_HSPACE_EXTRA + OP_TYPESTAR:
1447          case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:
1448          case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:
1449          count = 0;
1450    
1451          QS5:
1452          ADD_ACTIVE(state_offset + 2, 0);
1453          if (clen > 0)
1454            {
1455            BOOL OK;
1456            switch (c)
1457              {
1458              case 0x09:      /* HT */
1459              case 0x20:      /* SPACE */
1460              case 0xa0:      /* NBSP */
1461              case 0x1680:    /* OGHAM SPACE MARK */
1462              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1463              case 0x2000:    /* EN QUAD */
1464              case 0x2001:    /* EM QUAD */
1465              case 0x2002:    /* EN SPACE */
1466              case 0x2003:    /* EM SPACE */
1467              case 0x2004:    /* THREE-PER-EM SPACE */
1468              case 0x2005:    /* FOUR-PER-EM SPACE */
1469              case 0x2006:    /* SIX-PER-EM SPACE */
1470              case 0x2007:    /* FIGURE SPACE */
1471              case 0x2008:    /* PUNCTUATION SPACE */
1472              case 0x2009:    /* THIN SPACE */
1473              case 0x200A:    /* HAIR SPACE */
1474              case 0x202f:    /* NARROW NO-BREAK SPACE */
1475              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1476              case 0x3000:    /* IDEOGRAPHIC SPACE */
1477              OK = TRUE;
1478            break;            break;
1479    
1480            default:            default:
1481              OK = FALSE;
1482            break;            break;
1483            }            }
1484    
1485            if (OK == (d == OP_HSPACE))
1486              {
1487              if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||
1488                  codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)
1489                {
1490                active_count--;           /* Remove non-match possibility */
1491                next_active_state--;
1492                }
1493              ADD_NEW_DATA(-(state_offset + count), 0, 0);
1494              }
1495          }          }
1496        break;        break;
1497    
1498        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1499    #ifdef SUPPORT_UCP
1500        case OP_PROP_EXTRA + OP_TYPEEXACT:        case OP_PROP_EXTRA + OP_TYPEEXACT:
1501        case OP_PROP_EXTRA + OP_TYPEUPTO:        case OP_PROP_EXTRA + OP_TYPEUPTO:
1502        case OP_PROP_EXTRA + OP_TYPEMINUPTO:        case OP_PROP_EXTRA + OP_TYPEMINUPTO:
# Line 1236  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 1244  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 1289  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 1303  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 1313  for (;;) Line 1584  for (;;)
1584            { ADD_NEW_DATA(-state_offset, count, ncount); }            { ADD_NEW_DATA(-state_offset, count, ncount); }
1585          }          }
1586        break;        break;
1587    #endif
1588    
1589        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1590        case OP_ANYNL_EXTRA + OP_TYPEEXACT:        case OP_ANYNL_EXTRA + OP_TYPEEXACT:
# Line 1327  for (;;) Line 1599  for (;;)
1599          int ncount = 0;          int ncount = 0;
1600          switch (c)          switch (c)
1601            {            {
1602              case 0x000b:
1603              case 0x000c:
1604              case 0x0085:
1605              case 0x2028:
1606              case 0x2029:
1607              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1608              goto ANYNL03;
1609    
1610            case 0x000d:            case 0x000d:
1611            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1612            /* Fall through */            /* Fall through */
1613    
1614              ANYNL03:
1615              case 0x000a:
1616              if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
1617                {
1618                active_count--;           /* Remove non-match possibility */
1619                next_active_state--;
1620                }
1621              if (++count >= GET2(code, 1))
1622                { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }
1623              else
1624                { ADD_NEW_DATA(-state_offset, count, ncount); }
1625              break;
1626    
1627              default:
1628              break;
1629              }
1630            }
1631          break;
1632    
1633          /*-----------------------------------------------------------------*/
1634          case OP_VSPACE_EXTRA + OP_TYPEEXACT:
1635          case OP_VSPACE_EXTRA + OP_TYPEUPTO:
1636          case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
1637          case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
1638          if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
1639            { ADD_ACTIVE(state_offset + 4, 0); }
1640          count = current_state->count;  /* Number already matched */
1641          if (clen > 0)
1642            {
1643            BOOL OK;
1644            switch (c)
1645              {
1646            case 0x000a:            case 0x000a:
1647            case 0x000b:            case 0x000b:
1648            case 0x000c:            case 0x000c:
1649              case 0x000d:
1650            case 0x0085:            case 0x0085:
1651            case 0x2028:            case 0x2028:
1652            case 0x2029:            case 0x2029:
1653            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)            OK = TRUE;
1654              break;
1655    
1656              default:
1657              OK = FALSE;
1658              }
1659    
1660            if (OK == (d == OP_VSPACE))
1661              {
1662              if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)
1663              {              {
1664              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
1665              next_active_state--;              next_active_state--;
1666              }              }
1667            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1668              { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
1669            else            else
1670              { ADD_NEW_DATA(-state_offset, count, ncount); }              { ADD_NEW_DATA(-state_offset, count, 0); }
1671              }
1672            }
1673          break;
1674    
1675          /*-----------------------------------------------------------------*/
1676          case OP_HSPACE_EXTRA + OP_TYPEEXACT:
1677          case OP_HSPACE_EXTRA + OP_TYPEUPTO:
1678          case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
1679          case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
1680          if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
1681            { ADD_ACTIVE(state_offset + 4, 0); }
1682          count = current_state->count;  /* Number already matched */
1683          if (clen > 0)
1684            {
1685            BOOL OK;
1686            switch (c)
1687              {
1688              case 0x09:      /* HT */
1689              case 0x20:      /* SPACE */
1690              case 0xa0:      /* NBSP */
1691              case 0x1680:    /* OGHAM SPACE MARK */
1692              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1693              case 0x2000:    /* EN QUAD */
1694              case 0x2001:    /* EM QUAD */
1695              case 0x2002:    /* EN SPACE */
1696              case 0x2003:    /* EM SPACE */
1697              case 0x2004:    /* THREE-PER-EM SPACE */
1698              case 0x2005:    /* FOUR-PER-EM SPACE */
1699              case 0x2006:    /* SIX-PER-EM SPACE */
1700              case 0x2007:    /* FIGURE SPACE */
1701              case 0x2008:    /* PUNCTUATION SPACE */
1702              case 0x2009:    /* THIN SPACE */
1703              case 0x200A:    /* HAIR SPACE */
1704              case 0x202f:    /* NARROW NO-BREAK SPACE */
1705              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1706              case 0x3000:    /* IDEOGRAPHIC SPACE */
1707              OK = TRUE;
1708            break;            break;
1709    
1710            default:            default:
1711              OK = FALSE;
1712            break;            break;
1713            }            }
1714    
1715            if (OK == (d == OP_HSPACE))
1716              {
1717              if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)
1718                {
1719                active_count--;           /* Remove non-match possibility */
1720                next_active_state--;
1721                }
1722              if (++count >= GET2(code, 1))
1723                { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
1724              else
1725                { ADD_NEW_DATA(-state_offset, count, 0); }
1726              }
1727          }          }
1728        break;        break;
1729    
# Line 1379  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 1404  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 1412  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 1429  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 1451  for (;;) Line 1829  for (;;)
1829        break;        break;
1830    
1831        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1832          case OP_NOT_VSPACE:
1833          if (clen > 0) switch(c)
1834            {
1835            case 0x000a:
1836            case 0x000b:
1837            case 0x000c:
1838            case 0x000d:
1839            case 0x0085:
1840            case 0x2028:
1841            case 0x2029:
1842            break;
1843    
1844            default:
1845            ADD_NEW(state_offset + 1, 0);
1846            break;
1847            }
1848          break;
1849    
1850          /*-----------------------------------------------------------------*/
1851          case OP_VSPACE:
1852          if (clen > 0) switch(c)
1853            {
1854            case 0x000a:
1855            case 0x000b:
1856            case 0x000c:
1857            case 0x000d:
1858            case 0x0085:
1859            case 0x2028:
1860            case 0x2029:
1861            ADD_NEW(state_offset + 1, 0);
1862            break;
1863    
1864            default: break;
1865            }
1866          break;
1867    
1868          /*-----------------------------------------------------------------*/
1869          case OP_NOT_HSPACE:
1870          if (clen > 0) switch(c)
1871            {
1872            case 0x09:      /* HT */
1873            case 0x20:      /* SPACE */
1874            case 0xa0:      /* NBSP */
1875            case 0x1680:    /* OGHAM SPACE MARK */
1876            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1877            case 0x2000:    /* EN QUAD */
1878            case 0x2001:    /* EM QUAD */
1879            case 0x2002:    /* EN SPACE */
1880            case 0x2003:    /* EM SPACE */
1881            case 0x2004:    /* THREE-PER-EM SPACE */
1882            case 0x2005:    /* FOUR-PER-EM SPACE */
1883            case 0x2006:    /* SIX-PER-EM SPACE */
1884            case 0x2007:    /* FIGURE SPACE */
1885            case 0x2008:    /* PUNCTUATION SPACE */
1886            case 0x2009:    /* THIN SPACE */
1887            case 0x200A:    /* HAIR SPACE */
1888            case 0x202f:    /* NARROW NO-BREAK SPACE */
1889            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1890            case 0x3000:    /* IDEOGRAPHIC SPACE */
1891            break;
1892    
1893            default:
1894            ADD_NEW(state_offset + 1, 0);
1895            break;
1896            }
1897          break;
1898    
1899          /*-----------------------------------------------------------------*/
1900          case OP_HSPACE:
1901          if (clen > 0) switch(c)
1902            {
1903            case 0x09:      /* HT */
1904            case 0x20:      /* SPACE */
1905            case 0xa0:      /* NBSP */
1906            case 0x1680:    /* OGHAM SPACE MARK */
1907            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1908            case 0x2000:    /* EN QUAD */
1909            case 0x2001:    /* EM QUAD */
1910            case 0x2002:    /* EN SPACE */
1911            case 0x2003:    /* EM SPACE */
1912            case 0x2004:    /* THREE-PER-EM SPACE */
1913            case 0x2005:    /* FOUR-PER-EM SPACE */
1914            case 0x2006:    /* SIX-PER-EM SPACE */
1915            case 0x2007:    /* FIGURE SPACE */
1916            case 0x2008:    /* PUNCTUATION SPACE */
1917            case 0x2009:    /* THIN SPACE */
1918            case 0x200A:    /* HAIR SPACE */
1919            case 0x202f:    /* NARROW NO-BREAK SPACE */
1920            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1921            case 0x3000:    /* IDEOGRAPHIC SPACE */
1922            ADD_NEW(state_offset + 1, 0);
1923            break;
1924            }
1925          break;
1926    
1927          /*-----------------------------------------------------------------*/
1928        /* Match a negated single character. This is only used for one-byte        /* Match a negated single character. This is only used for one-byte
1929        characters, that is, we know that d < 256. The character we are        characters, that is, we know that d < 256. The character we are
1930        checking (c) can be multibyte. */        checking (c) can be multibyte. */
# Line 1481  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 1519  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 1555  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 1587  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 1622  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 1730  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 1768  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 1777  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 1789  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 1820  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 1972  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 1989  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 2006  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 2073  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_DATA_SCOPE 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 2163  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    
2702  switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : options) &  switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
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;
2712    default: return PCRE_ERROR_BADNEWLINE;    default: return PCRE_ERROR_BADNEWLINE;
2713    }    }
2714    
2715  if (newline < 0)  if (newline == -2)
2716      {
2717      md->nltype = NLTYPE_ANYCRLF;
2718      }
2719    else if (newline < 0)
2720    {    {
2721    md->nltype = NLTYPE_ANY;    md->nltype = NLTYPE_ANY;
2722    }    }
# Line 2228  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 2239  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 2256  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 2264  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 2276  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          else if (startline)
2864            {
2865            if (current_subject > md->start_subject + start_offset)
2866              {
2867    #ifdef SUPPORT_UTF8
2868              if (utf8)
2869                {
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, and we            /* If we have just passed a CR and the newline option is ANY or
2885          are now at a LF, advance the match position by one more character. */            ANYCRLF, and we are now at a LF, advance the match position by one
2886              more character. */
2887          if (current_subject[-1] == '\r' &&  
2888               md->nltype == NLTYPE_ANY &&            if (current_subject[-1] == CHAR_CR &&
2889               current_subject < end_subject &&                 (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
2890               *current_subject == '\n')                 current_subject < end_subject &&
2891            current_subject++;                 *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 2350  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 2395  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 2425  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, and we    /* If we have just passed a CR and we are now at a LF, and the pattern does
3008    are now at a LF, advance the match position by one more character. */    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. */
3010    if (current_subject[-1] == '\r' &&  
3011         (md->nltype == NLTYPE_ANY || md->nllen == 2) &&    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 &&
3015            (md->nltype == NLTYPE_ANY ||
3016             md->nltype == NLTYPE_ANYCRLF ||
3017             md->nllen == 2))
3018      current_subject++;      current_subject++;
3019    
3020    }   /* "Bumpalong" loop */    }   /* "Bumpalong" loop */

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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12